Skip to content

Instantly share code, notes, and snippets.

@zdennis
Created August 8, 2019 18:15
Show Gist options
  • Save zdennis/16b43c585f3d24a6e834d5aa6bcba16c to your computer and use it in GitHub Desktop.
Save zdennis/16b43c585f3d24a6e834d5aa6bcba16c to your computer and use it in GitHub Desktop.
Rails 2 to Rails 3: find duplicate callback registrations
# When moving from Rails 2 to Rails 3 a change in
# callback behavior can cause issues because
# you can now only have one callback that calls a
# specific method, e.g.
#
# after_save :foo, if: :bar?
# after_save :foo, if: :baz?
#
# In the above only the second callback will be stored. The first
# one with the condition on bar? will not appear in the callback chain.
#
# This is the line in ActiveSupport that causes this to happen:
# https://github.com/rails/rails/blob/0c0f278ab20f3042cdb69604166e18a61f8605ad/activesupport/lib/active_support/callbacks.rb#L500
#
# This is how Rails works up to Rails 5.2 as well. Haven't checked 6.0 yet.
dirs2check = %w(app config lib spec vendor)
duplicates = []
failed = []
dirs2check.each do |dir|
Dir["#{dir}/**/*.rb"].each do |file|
file_duplicates = []
begin
contents = File.read(file)
rescue => ex
failed << "#{filed} failed to be read because of #{ex.message}"
next
end
hash = {}
begin
contents.scan(/\b((after|before)_(save|update|commit|destroy))[ \(](:\w+)/).map do |callback, _, _, method|
key = "#{callback} #{method}"
if hash.key?(key)
file_duplicates << "#{file}: #{key} is duplicated"
else
hash[key] = true
end
end
rescue => ex
failed << "#{file} failed to be read because of #{ex.message}"
next
end
if file_duplicates.empty?
puts "#{file} \e[32mno duplicates\e[0m"
else
duplicates.concat file_duplicates
end
end
end
puts
puts
puts "Duplicates found: #{duplicates.length}"
puts duplicates
puts
puts "Failures:"
puts failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment