Как добавить ассоциацию has_many на всех моделях - PullRequest
1 голос
/ 22 апреля 2010

Сейчас у меня есть инициализатор, который делает это:

ActiveRecord::Base.send :has_many, :notes, :as => :notable ActiveRecord::Base.send :accepts_nested_attributes_for, :notes

Он прекрасно строит связь, за исключением того, что когда я загружаю представление, которое его использует, вторая загрузка дает мне can't dup NilClass от:

/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_scoped_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'

Есть идеи? Я делаю это неправильно? Интересно, что если я перенесу ассоциацию только на модель, с которой работаю в данный момент, я не получу эту ошибку Я полагаю, что неправильно строю глобальную ассоциацию.

Ответы [ 4 ]

7 голосов
/ 22 апреля 2010

Вы заявляете, что у вас есть много моделей, каждая из которых требует этой ассоциации. Если бы это был я, я бы пошел с подходом создания класса базовой модели, который содержит ассоциацию, а затем наследовал бы все другие модели. Что-то вроде:

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

По моему мнению, этот подход более самодокументирован по сравнению с использованием небольшого количества метапрограммирования, скрытого в инициализаторе.

0 голосов
/ 22 апреля 2010

Благодаря Ричу Килмеру (из InfoEther) мы нашли элегантный (и слегка непрозрачный) способ исправить это:

# 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

Теперь наследование не изменяется, и оно очень СУХОЕ

0 голосов
/ 22 апреля 2010

Рекомендуется создавать каждую ассоциацию в каждой модели! Это бесполезный СУХОЙ способ делать такие вещи! Вообще, это мое мнение!

0 голосов
/ 22 апреля 2010

взгляните на без загрузки это может помочь вам

...