【问题标题】:Rails nested form many-to-many special caseRails 嵌套形成多对多的特殊情况
【发布时间】:2013-08-27 19:52:29
【问题描述】:

让我们考虑一下 Rails 中多对多模型的经典实现。

class Order
  has_many   :order_products
  has_many   :products, through: order_products
  accepts_nested_attributes_for :order_products
end

class Product
  has_many :order_products
  has_many :orders, through: order_products
end

class OrderProduct
  belongs_to :order
  belongs_to :product
  accepts_nested_attributes_for :products
end

<%= form_for(@order) do |f| %>
  <% f.fields_for :order_products do |op|%>
  <%= op.label :amount %><br>
  <%= op.text_field :amount %>

  <% op.fields_for :product do |p|%>
     <%= p.label :name %><br>
     <%= p.text_field :name %>
  <% end %>
<% end %>

问题在于我有一个完整的常量表 products,其中包含预定义的产品集。我需要在 订单 的创建/编辑视图上显示所有 产品 列表,并且用户应该设置他需要的每个产品的数量,没有办法添加额外的产品。 order_products 是一个连接表。

在经典示例中,用户可以自己添加/删除产品到 products 表中,在我的情况下,他只能从预定义的集合中选择需要的产品,并且他的选择应该记录在 order_products 表。

上面的代码是为经典案例给出的,我不知道如何适应我的案例。

感谢您的帮助。

附录: 以下是我现在拥有的代码

<%= form_<%= form_for(@order) do |f| %>
  <% f.fields_for :order_products do |op|%>
  <%= op.label :amount %><br>
  <%= op.text_field :amount %>
  <%= op.label :product_id, "Product" %>
  <%= op.select :product_id, Product.all.collect { |p| [p.name, p.id] } %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

我必须将以下代码添加到订单控制器,以创建所有不包含的产品以 0 数量订购,以便所有产品都在表单上。这不是最好的方法,你知道如何正确地做吗?

Product.all.each { |p| order.orderproducts.push(OrderProduct.new(:product_id => p.id,:order_id => 1, :amount => 0)) if !@order.orderproducts.any?{|b| b.product_id == p.id}}

【问题讨论】:

    标签: ruby-on-rails forms nested-forms


    【解决方案1】:

    您似乎需要OrderProduct 上的amount 列/属性,并且您可以删除该类上的嵌套产品声明。

    然后,您可以根据您的订单创建OrderProduct 实例,指定您想要的产品和该产品的数量。您不需要任何产品的嵌套,因为您已经创建了这些。

    然后你的表单会变成这样:

    <%= form_for(@order) do |f| %>
      <% f.fields_for :order_products do |op|%>
      <%= op.label :amount %><br>
      <%= op.text_field :amount %>
      <%= op.label :product_id, "Product" %>
      <%= op.select :product_id, Product.all.collect { |p| [p.name, p.id] } %>
    <% end %>
    

    还值得为您的OrderProduct 添加验证,以确保amount 是有效的正整数。

    validates_numericality_of :amount, 
        :only_integer => true, 
        :greater_than_or_equal_to => 0
    

    【讨论】:

    • 非常感谢您的回答,我已将当前代码添加到问题的附录中。问题是我无法让它工作,它失败了'unexpected keyword_ensure,expecting $end'。我做错了什么?
    • 您有两个 &lt;% end %&gt; 语句来关闭您的表单。
    • 对,谢谢,我在附录中也改了,但现在我有一些不同的未定义的局部变量或方法`form_' for
    • 这是从您的代码中复制的错误。已在我的回答中修复。
    • 太好了,谢谢!还有一点,问题是我需要表格上所有可用产品的列表,如果产品不包含在订单中,只需显示数量为 0。我不知道如何以 Rails 方式正确实现它,我添加到附录中的唯一解决方法,您知道更好的方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多