我是Rails的新手,这是我在StackOverflow上的第一篇文章。
说我有3个型号:
class Product < ActiveRecord::Base
default_scope :order => :title
has_many :line_items
has_many :promo_products
has_many :promotions, :through => :promo_products, :foreign_key => :promotion_id
before_destroy :ensure_not_referenced_by_any_line_item
before_destroy :ensure_not_referenced_by_any_promo_product
validates :title, :presence => true, :uniqueness => true
validates :description, :presence => true
validates :price, :numericality => {:greater_than_or_equal_to => 0.01}
private
def ensure_not_referenced_by_any_line_item
if line_items.empty?
return true
else
errors.add(:base, 'Line Items present')
return false
end
end
def ensure_not_referenced_by_any_promo_product
if promo_products.empty?
return true
else
errors.add(:base, 'Some promotions are still in effect')
return false
end
end
end
class Promotion < ActiveRecord::Base
CART_OR_PRODUCT = ['Cart', 'Product']
PROMOTION_TYPE = ['Percentage based', 'Value based']
has_many :promo_products
accepts_nested_attributes_for :promo_products
has_many :products, :through => :promo_products, :foreign_key => :product_id
accepts_nested_attributes_for :products
#attr_accessible :promo_products_attributes, :title, :description, :cart_or_product, :promotion_type, :discount, :minimum_price, :minimum_quantity
validates :title, :description, :presence => true
validates :cart_or_product, :inclusion => {:in => CART_OR_PRODUCT, :message =>
"is invlaid. Please select a valid option"}
validates :promotion_type, :inclusion => {:in => PROMOTION_TYPE, :message =>
"is invalid. Please select a valid option"}
validates :discount, :minimum_price, :numericality => {:greater_than_or_equal_to => 0.00}
validates :minimum_quantity, :numericality => {:greater_than_or_equal_to => 0}
end
class PromoProduct < ActiveRecord::Base
belongs_to :promotion
belongs_to :product
accepts_nested_attributes_for :products
end
在促销新页面中,我想展示可能属于促销活动的产品列表。用户可以选择0个,1个或更多产品,具体取决于促销类型。
在promotion_controller的新动作中,我构建如下:
@promotion.promo_products.build.build_product
在_form促销活动中,我需要显示供用户选择的产品列表。我做了一个嵌套的形式,如:
<%= form_for(@promotion) do |f| %>
<!-- other promotion fields -->
<%= f.fields_for :promo_products do |pp| %>
<%= pp.fields_for :products do |p| %>
<div class="field">
<%= f.label "Products" %><br />
<%= collection_select :promo_product, :product_id, Product.all, :id, :title {:selected => @promotion.product_ids}, {:multiple => true} %>
</div>
<% end %>
<% end %>
<% end %>
我有2个问题。
数据未保存到promo_product表。我在promo_product控制器中创建了动作:
def create
@promotion = current_promotion
products = Product.select(:id => params[:product_id])
products.each do |p|
promo_product = @promotion.promo_products.build(p)
promo_product.save
end
#@promo_product = PromoProduct.new(params[:promo_product])
redirect_to promotions_path
end
我该怎么办呢?
谢谢。
答案 0 :(得分:1)
您不应将“accept_nested_attribute_for”放在关联表PromoProducts中。它应该存在于您要用于创建与另一个模型的关联的模型中。 “accept_nested_attribute_for”IIRC只是为您的模型插入“[association] _attributes =”方法。例如,如果将此方法添加到Promotion类的Product类中,则会在Product类中插入“promotion_attributes =”方法。然后,嵌套表单可以使用此函数创建具有表示模型和关联的哈希的新对象。
基于以上所述,创建操作不应该在PromoProduct控制器中,而应该在Promotion控制器中。
<%= form_for(@promotion) do |f| %>
<!-- other promotion fields -->
<%= f.fields_for :products do |pp| %>
<div class="field">
<%= f.label "Products" %><br />
<%= collection_select :promo_product, :product_id, Product.all, :id, :title {:selected => @promotion.product_ids}, {:multiple => true} %>
</div>
<% end %>
<% end %>
如果上面的collection_select行正确无误,我不知道。但是,您可以通过将表单返回的参数检查到服务器控制台日志中的控制器来进行调试。基本上你应该看到
的嵌套哈希{:promotion => {:products => ...}}
如果您需要更多帮助,请与我们联系。在我的解决方案中,我使用了select_tag和options_from_collection_for_select的组合。 (但是,如果不查看API文档,我不记得所有这些行为的行为。)
最后,你需要:通过型号吗?我想想,因为您创建了直通模型,您需要在创建操作中保存它。但是,由于您在PromoProducts表上没有其他属性,我想知道您是否只想将其作为HABTM关联并让rails处理其余的?