Class: RuboCop::Cop::YiffSpace::BelongsToUser

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
NodeFormattingHelper
Defined in:
lib/rubocop/cop/yiff_space/belongs_to_user.rb

Overview

Enforces using ‘belongs_to_user` instead of `belongs_to` for User associations. `belongs_to_user` provides additional helper methods and is the project standard for any relation backed by a User record.

It matches both ‘belongs_to(:user)` and associations with an explicit `class_name: “User”` option, auto-correcting both forms.

The class name is configurable via ‘ClassName` (default: `User`). The inferred attribute name is the snake_case of the last segment (e.g. `ClassName: CurrentUser` matches `belongs_to(:current_user)`).

Examples:

# bad
belongs_to(:user)

# bad
belongs_to(:creator, class_name: "User")

# good
belongs_to_user(:user)

# good
belongs_to_user(:creator)

ClassName: CurrentUser

# bad
belongs_to(:current_user, optional: false)

# bad
belongs_to(:creator, class_name: "CurrentUser")

# good
belongs_to_user(:current_user, optional: false)

# good
belongs_to_user(:creator)

Constant Summary collapse

MSG =
"Use `belongs_to_user(%<attr>s)` instead of `belongs_to(%<attr>s)`"

Constants included from NodeFormattingHelper

NodeFormattingHelper::BASIC

Instance Method Summary collapse

Methods included from NodeFormattingHelper

#format_node

Instance Method Details

#belongs_to_user?(node) ⇒ Object



57
58
59
# File 'lib/rubocop/cop/yiff_space/belongs_to_user.rb', line 57

def_node_matcher(:belongs_to_user?, <<~PATTERN)
  (send nil? :belongs_to $_ $...)
PATTERN

#on_csend(node) ⇒ Object



82
83
84
# File 'lib/rubocop/cop/yiff_space/belongs_to_user.rb', line 82

def on_csend(node)
  on_send(node)
end

#on_send(node) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rubocop/cop/yiff_space/belongs_to_user.rb', line 61

def on_send(node)
  belongs_to_user?(node) do |receiver, code|
    return unless receiver.type?(:str, :sym)

    attr = format_node(receiver)

    return if attr.nil? || attr.empty? || !code.last&.hash_type?

    options = format_node(code.last, {})

    # Match belongs_to(:user) (or configured attr name)
    if attr.to_sym == user_attr_name && !options.key?(:class_name)
      register_offense(node, attr, options)
      return
    end

    # Match belongs_to(attr, class_name: "User") (or configured ClassName)
    register_offense(node, attr, options) if options[:class_name] == user_class_name
  end
end