开发者

How to add a has_many association on all models

开发者 https://www.devze.com 2022-12-28 07:15 出处:网络
Right now I have an initializer that does this: ActiveRecord::Base.send :has_many, :notes, :as => :notable

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

0

精彩评论

暂无评论...
验证码 换一张
取 消