How to add a has_many association on all models
Right now I have an initializer that does this:
ActiveRecord::Base.send :has_many, :notes, :as => :notable
ActiveRecord::Base.send :accepts_nested_attributes_for, :notes
It builds the association just fine, except when I load a view that uses it, the second load gives me:
can't dup NilClass
from:
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2184:in `dup'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2184:in `scoped_methods'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2188:in `current_scope开发者_如何学God_methods'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2171:in `scoped?'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2439:in `send'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2439:in `initialize'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:162:in `new'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:162:in `build_association'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:423:in `build_record'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations/association_collection.rb:102:in `build'
(my app)/controllers/manifests_controller.rb:21:in `show'
Any ideas? Am I doing this the wrong way? Interestingly if I move the association onto just the model I'm working with at the moment, I don't get this error. I figure I must be building the global association incorrectly.
You state that you have many models, all of which require this association. If it were me, I'd would go with the approach of creating a base model class that contains the association and then have all the other models inherit from it. Something like:
class NotableModel < ActiveRecord::Base
# Prevents ActiveRecord from looking for a database table for this class
self.abstract_class = true
has_many :notes, :as => :notable
accepts_nested_attributes_for :notes
end
class Foo < NotableModel
...
end
class Bar < NotableModel
...
end
In my opinion this approach is more self-documenting compared to using a little bit of metaprogramming hidden away in an initializer.
take a look at unloadable it may help you
It's recommended to make each association in each model! It's a useless DRY way to make such things! At all, It's my opinion!
Thanks to Rich Kilmer (of InfoEther), we found the elegant (and slightly opaque) way of fixing this:
# config/initializers/has_many_notes.rb
module ActiveRecord
class Base
def self.inherited(klass)
super
klass.send :has_many, :notes, :as => :notable
klass.send :accepts_nested_attributes_for, :notes
end
end
end
Now no inheritance changes, and it's very DRY
精彩评论