我正在尝试使用 Rails 多态关联和嵌套表单创建一篇包含 in_prices 和 out_prices (每个国家/地区一个)的文章。
我有一个看起来像这样的数据模型:
# app/models/article.rb
class Article < ActiveRecord::Base
has_many :out_prices, :class_name => "Price", :as => :priceable
has_many :in_prices, :class_name => "Price", :as => :priceable
end
# app/models/price.rb
class Price < ActiveRecord::Base
belongs_to :priceable, :polymorphic => true
end
# db.schema for prices
create_table "prices", :force => true do |t|
t.integer "value"
t.integer "country_id"
t.integer "priceable_id"
t.string "priceable_type"
end
文章及其关联是使用嵌套形式创建的,例如:
# app/views/articles/_article_form.html.erb
<%= form_for setup_article(@article) do |f| %>
<%= f.fields_for :in_prices do |ff| %>
<%= ff.text_field :value %>
<% end %>
<%= f.fields_for :out_prices do |ff| %>
<%= ff.text_field :value %>
<% end %>
<% end %>
setup_article 方法是建立关联的辅助方法:
# app/helpers/articles_helper.rb
def setup_article(article)
if article.in_prices.nil?
# Setup one in price for each country
Country.all.each do |country|
article.in_prices.build(:value => 0, :country_id => country.id)
end
end
if article.out_prices.nil?
# Setup one out price for each country
Country.all.each do |country|
article.out_prices.build(:value => 0, :country_id => country.id)
end
end
article
end
需要 setup_article 以确保在创建新文章时显示空的价格表单字段(每个国家/地区一个)。
现在到实际问题。当我编辑已经创建的文章(关联了 in_prices 和 out_prices)时,Rails 将无法区分这些不同类型的多态关联(in_prices 和 out_prices)。因此,两个嵌套的表单助手都会为所有相关价格呈现表单字段,这不是所需的行为。我只想在其中一种嵌套形式中列出 in_prices,而在另一种形式中列出 out_prices。
应该如何配置这些关联以确保 rails 可以区分两个不同嵌套表单助手中的 in_prices 和 out_prices 关联?
编辑(已解决)
我的一个朋友指出我需要在价格表中添加另一个字段来标记它是什么类型的价格。我将此字段称为 price_type 并且 db.schema 最终看起来像这样:
# db.schema for prices
create_table "prices", :force => true do |t|
t.integer "value"
t.integer "price_type"
t.integer "country_id"
t.integer "priceable_id"
t.string "priceable_type"
end
注意:不要将此字段命名为“类型”,因为这是保留名称。
可以通过在嵌套表单中添加隐藏字段(不太安全)来填充“price_type”字段,或者在保存文章及其相关数据之前在控制器中处理它。我选择将其添加为隐藏参数,例如:
# app/views/articles/_article_form.html.erb
<%= form_for setup_article(@article) do |f| %>
<%= f.fields_for :in_prices do |ff| %>
<%= ff.text_field :value %>
<%= ff.text_field :price_type, :value => "in" %>
<% end %>
<%= f.fields_for :out_prices do |ff| %>
<%= ff.text_field :value %>
<%= ff.text_field :price_type, :value => "out" %>
<% end %>
<% end %>
为了确保关联被正确过滤,它们需要使用 ':conditions' 标签声明,例如:
# app/models/article.rb
class Article < ActiveRecord::Base
has_many :out_prices, :class_name => "Price", :as => :priceable, :conditions => { :price_type => "in" }
has_many :in_prices, :class_name => "Price", :as => :priceable, :conditions => { :price_type => "out" }
end
..现在一切都按预期工作。干杯!