class RuboCop::Cop::Rails::ContentTag

This cop checks legacy syntax usage of `tag`

NOTE: Allow `tag` when the first argument is a variable because

`tag(name)` is simpler rather than `tag.public_send(name)`.
And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 2.0)

@example

# bad
tag(:p)
tag(:br, class: 'classname')

# good
tag.p
tag.br(class: 'classname')
tag(name, class: 'classname')

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_new_investigation() click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 31
def on_new_investigation
  @corrected_nodes = nil
end
on_send(node) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 35
def on_send(node)
  first_argument = node.first_argument
  return if !first_argument ||
            allowed_argument?(first_argument) ||
            corrected_ancestor?(node)

  preferred_method = node.first_argument.value.to_s.underscore
  message = format(MSG, preferred_method: preferred_method, current_argument: first_argument.source)

  add_offense(node, message: message) do |corrector|
    autocorrect(corrector, node, preferred_method)

    @corrected_nodes ||= Set.new.compare_by_identity
    @corrected_nodes.add(node)
  end
end

Private Instance Methods

allowed_argument?(argument) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 58
def allowed_argument?(argument)
  argument.variable? ||
    argument.send_type? ||
    argument.const_type? ||
    argument.splat_type? ||
    allowed_name?(argument)
end
allowed_name?(argument) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 75
def allowed_name?(argument)
  return false unless argument.str_type? || argument.sym_type?

  !/^[a-zA-Z\-][a-zA-Z\-0-9]*$/.match?(argument.value)
end
autocorrect(corrector, node, preferred_method) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 66
def autocorrect(corrector, node, preferred_method)
  range = correction_range(node)

  rest_args = node.arguments.drop(1)
  replacement = "tag.#{preferred_method}(#{rest_args.map(&:source).join(', ')})"

  corrector.replace(range, replacement)
end
corrected_ancestor?(node) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 54
def corrected_ancestor?(node)
  node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
end
correction_range(node) click to toggle source
# File lib/rubocop/cop/rails/content_tag.rb, line 81
def correction_range(node)
  range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
end