Skip to content

Instantly share code, notes, and snippets.

@sikachu
Last active September 9, 2022 05:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sikachu/75a3c16922fa58c3c27715b5ffdbd18a to your computer and use it in GitHub Desktop.
Save sikachu/75a3c16922fa58c3c27715b5ffdbd18a to your computer and use it in GitHub Desktop.
RuboCop cop to check and warn for duplicate call to `ActiveRecord::Base.ignore_columns=`
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# Checks for duplicate calls to ActiveRecord::Base.ignore_columns= as the
# subsequent calls will override the first call.
#
# @example
# # bad
# class User < ApplicationRecord
# self.ignored_columns = %w(profile)
# self.ignored_columns = %w(birthday)
# end
#
# # good
# class User < ApplicationRecord
# self.ignored_columns = %w(profile birthday)
# end
#
class AvoidDuplicateIgnoredColumns < Cop
MESSAGE = "self.ignored_columns= has already been called on line " \
"%{other_line_number}".freeze
ACTIVE_RECORD_CLASSES = %w(
ApplicationRecord
ActiveRecord::Base
).freeze
def initialize(config = nil, options = nil)
super
@found_nodes = {}
@reported_lines = []
end
def on_send(current_node)
return unless current_node.method_name == :ignored_columns=
return unless current_node.self_receiver?
parent_class_name = find_parent_class_name(current_node)
return unless active_model?(parent_class_name)
@found_nodes[current_node.first_line] = current_node
return if @found_nodes.size == 1
add_offences
end
private
def active_model?(parent_class_name)
ACTIVE_RECORD_CLASSES.include?(parent_class_name)
end
def find_parent_class_name(node)
return nil unless node
if node.class_type?
parent_class_name = node.node_parts[1]
return nil if parent_class_name.nil?
return parent_class_name.source
end
find_parent_class_name(node.parent)
end
def add_offences
@found_nodes.each do |line_number, node|
next if @reported_lines.include?(line_number)
other_line_number = (@found_nodes.keys - [line_number]).first
add_offense(
node,
message: format(MESSAGE, other_line_number: other_line_number)
)
@reported_lines << line_number
end
end
end
end
end
end
@HarlemSquirrel
Copy link

@sikachu this is great! You should open a PR into https://github.com/rubocop/rubocop-rails

@sikachu
Copy link
Author

sikachu commented Jan 5, 2022

@HarlemSquirrel oh, ha, I actually promised my colleague that I'll submit this patch upstream ... so thank you for the ping. Glad that you find it useful.

And yes, will do. 👍

@HarlemSquirrel
Copy link

♥️

@sikachu
Copy link
Author

sikachu commented Sep 9, 2022

I submitted this to rubocop-rails here: rubocop/rubocop-rails#761

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment