这是我的模特:
class Speaker < ActiveRecord::Base
belongs_to :session, :foreign_key => :session_id, :class_name => :Session
belongs_to :speakable, :polymorphic => true
end
class Session < ActiveRecord::Base
has_many :speakers
accepts_nested_attributes_for :speakers
end
class Person < ActiveRecord::Base
has_many :speakers, :as => :speakable
end
class Company < ActiveRecord::Base
has_many :speakers, :as => :speakable
end
我现在要做的是这样的事情: 应用程序/视图/会话/ edit.html.erb
<% f.fields_for :speakers do |sf| %>
<p>
<%= sf.label :speaker %><br />
<%= sf.collection_select :speakable, Company.all + Person.all, :id, :full_name %>
</p>
<% end %>
但由于多态分配,它无法正常工作。我该如何处理这个问题?
编辑: 错误是:
undefined method `base_class' for String:Class
以params为:
"speaker"=>{"speakable"=>"1063885469", "session_id"=>"1007692731"}
传递给speakable的价值是演讲者/公司的ID。是的,这是我指定要返回collection_select
的值,但我如何设法提供这两个值(speakable_id
和speakable_type
)?
答案 0 :(得分:1)
您可以使用hidden_field
保存speakable_type
。这样,每次所选选项更改时,您都必须更改hidden_field
的值。我不确定这是最好的方法,但有效......
希望它对你有所帮助。
修改强>
您必须在选择中定义:onchange
选项。
<%= sf.collection_select :speakable, Company.all + Person.all, :id,
:full_name, {}, {:onchange => "setSpeakableType()"} %>
hidden_field
以nil
值开头。
<%= sf.hidden_field :speakable_type, :value => nil %>
您的setSpeakableType()
函数必须设置正确的speakable_type
。
答案 1 :(得分:0)
我解决了这个问题的两种方法。
第一种是在表单中处理你的集合,这样你就可以确定id的开头类型。类似的东西:
然后在你的控制器动作中:
def action
if params[:speaker][:speakable].begins_with?("Person:")
speak_type = 'Person'
speak_id = params[:speaker][:speakable].split(":")[1].to_i
elsif params[:speaker][:speakable].begins_with?("Company:")
speak_type = 'Company'
speak_id = params[:speaker][:speakable].split(":")[1].to_i
end
params[:speaker].delete(:speakable)
obj = Speaker.new(params[:speaker])
obj.speaker_type = speak_type
obj.speaker_id = speak_id
... rest of action ...
end
第二种是使用javascript来更改隐藏在页面中的隐藏字段speakable_type和speakable_id。我最终使用自动填充器来填充此字段,因此在进行选择时调用javascript非常简单。第二种方法使控制器更强大批次。