Last active
September 9, 2022 05:47
-
-
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=`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 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. 👍
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
@sikachu this is great! You should open a PR into https://github.com/rubocop/rubocop-rails