元素的多态关联,还需要添加其他东西吗?

时间:2012-07-13 17:32:45

标签: ruby-on-rails-3 activerecord

我已经采纳了,我不确定为什么某些东西不起作用。

我有一个可维护的多态关联,我只使用一个名为Item的模型。它看起来像这样:

class Item < ActiveRecord::Base
  #price
  has_one :price, :as => :pricable
  accepts_nested_attributes_for :price

  attr_accessible :price_attributes, :price, ....

我想添加一个事件模型,并添加了以下内容:

class Event < ActiveRecord::Base
  #price
  has_one :price, :as => :pricable
  accepts_nested_attributes_for :price
  attr_accessible :price, :price_attributes

但是,我无法设置它:

ruby-1.9.2-p290 :001 > e=Event.find(19) #ok
ruby-1.9.2-p290 :002 > e.price
Creating scope :page. Overwriting existing method Price.page.
  Price Load (0.8ms)  SELECT `prices`.* FROM `prices` WHERE `prices`.`pricable_id` = 19 AND `prices`.`pricable_type` = 'Event' LIMIT 1
 => nil 
ruby-1.9.2-p290 :003 > e.price.price=23
NoMethodError: undefined method `price=' for nil:NilClass
    from /Users/jt/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.0/lib/active_support/whiny_nil.rb:48:in `method_missing'
    from (irb):3

嗯....看起来关系设置正确并且事件可以通过attr_accessible访问价格。知道还有什么可以继续吗?

THX

2 个答案:

答案 0 :(得分:1)

关系似乎是正确定义的,但是如果e.price返回nil,那么显然e.price.price =将无效并返回未定义的方法错误。您需要首先构建/创建关联的价格对象:

> e = Event.find(19)
=> #<Event id: 19, ...>
> e.price
=> nil
> e.create_price(price: 23)
=> #<Price id: 1, priceable_id: 19, price: 23, ...>

或者如果您想使用嵌套属性:

> e = Event.find(19)
=> #<Event id: 19, ...>
> e.price
=> nil
> e.update_attributes(price_attributes: { price: 23 })
=> true
> e.price
=> #<Price id: 1, priceable_id: 19, price: 23, ...>

答案 1 :(得分:1)

这就是你的模型应该是这样的

class Price < ActiveRecord::Base
  attr_accessible :value
  belongs_to :priceable, :polymorphic => true
end

class Item < ActiveRecord::Base
   attr_accessible :name, :price_attributes
   has_one :price, :as => :priceable
   accepts_nested_attributes_for :price
end

class Event < ActiveRecord::Base
  attr_accessible :name, :price_attributes
  has_one :price, :as => :priceable
  accepts_nested_attributes_for :price
end

这是您的价格迁移应该是这样的

class CreatePictures < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.string  :name
      t.integer :imageable_id
      t.string  :imageable_type
      t.timestamps
    end
  end
end

然后你可以轻松地做这样的事情

Item.new( { name: 'John', price_attributes: { value: 80 } } )