一对一的多态性

时间:2011-02-28 09:54:14

标签: ruby-on-rails ruby-on-rails-3 polymorphism

我有两种类型的“所有者”,每种都可以有一个“偏好”。

这是我目前的设置(即我想象一对一的多态将起作用):

Company.rb
  has_one :pref, :as => :owner

Representative.rb
  has_one :pref, :as => :owner

Pref.rb
  belongs_to :owner, :polymorphic => true

然后我尝试以下命令:

Company.first.owner => nil
Company.first.owner.build => error

如何让这种关系有效?


更新:有关错误的详细信息

NoMethodError: undefined method `build' for nil:NilClass
from /Users/san/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.1/lib/active_support/whiny_nil.rb:48:in `method_missing'
from (irb):10
from /Users/san/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
from /Users/san/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
from /Users/san/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.0.1/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

我的迁移:

create_table :prefs do |t|
    t.integer :owner_id, :null => true
    t.string :owner_type, :null => true
    ...
end

最后一个问题

# after manually building a pref to link to this representative...
Representative.first.pref => finds pref
Representative.last.pref.create => error

NoMethodError: undefined method `new' for "#<Pref:0x00000106a18ce8>":Pref
from /Users/san/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.0.1/lib/active_record/associations/association_proxy.rb:212:in `method_missing'

这太令人困惑了!


答案:

请参阅:Using build with a has_one association in rails

Representative.last.build_pref => works

2 个答案:

答案 0 :(得分:1)

错误是什么?您是否正确迁移了数据库?即:

t.string :owner_type
t.integer :owner_id

答案 1 :(得分:1)

这是一种扭曲的关系,但是......我宁愿这样做:

记住:ownerable_type,:ownerable_id字段。

Company.rb
  has_one  :owner, :as => :ownerable

Representative.rb
  belongs_to :ownerable, :polymorphic => true

Owner.rb
  belongs_to :ownerable, :polymorphic => true

之后

Company.first.owner, should work

以及

Owner.first.ownerable

应该退回公司

事实上,当你有以下情况时,对我来说似乎更好:

Company.rb
  belongs_to :ownerable, :polymorphic => true

Representative.rb
  has_many :companies, :polymorphic => true, :as => :ownerable

Owner.rb
  has_many :companies, :polymorphic => true, :as => :ownerable

当然可以切换到has_one。