A few things I learned about ActiveRecord after_create (and other callbacks)

1. after_create does not get inherited
class Animal < ActiveRecord::Base

after_create :feed_on_milk
def feed_on_milk

self.immunity_level += 1

end

end

class Cat < Animal
end

The after_create does not get inherited, and so our poor little cats won't get milk! To retain the after_create hook, you'll need to do:
class Cat < Animal

after_create :feed_on_milk

end

2. after_create is an array of symbols

If you call after_create on same symbol :foo twice, the ‘foo’ method will be executed twice. I had a bug in my code because I had something like:

class Animal < ActiveRecord::Base

after_create :feed_on_milk

end

and at the same time somewhere else I had something like:

klasses = [… ,Animal, …]
klasses.each do |klass|

klass.class_eval do

after_create :feed_on_milk

end

end

So, :feed_on_milk symbol got added to the array twice, and so the method got executed twice, and I had to do this instead:

klass.class_eval do

after_create(:feed_on_milk) unless self.after_create.include?(:feed_on_milk)

end

3. after_create is one of many ClassInheritableAttributes

The reason behind 1. and 2. is that Rails extends Class to have these “attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of their parents’ attributes, instead of just a pointer to the same.”

See vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb

discussion by DISQUS
Add New Comment