Rails中的循环索引操作不起作用

时间:2014-11-05 00:58:11

标签: ruby-on-rails ruby-on-rails-4

我的订单视图中有以下代码:

<div class="grid heading">
  <div class="grid wrap">
    <div class=" unit whole">
      <h1>Orders</h1>
    </div>
  </div>
</div>

<div class="grid wrap">
  <div class="unit whole">
    <p id="notice"><%= flash[:notice] %></p>
    <p id="alert"><%= flash[:alert] %></p>
  </div>
</div>

<% @vendors.each do |vendor| %>
  <h2><%= vendor.name %></h2>
  <% @locations.each do |location| %>
    <h3><%= location.address %></h3>
    <% @orders.each do |order| %>
      <div class="grid wrap">
        <div class="unit whole">
          <table>
            <thead>
              <tr>
                <th>SKU</th>
                <th>Description</th>
              </tr>
            </thead>
            <tbody>
              <% order.line_items.each do |line_item| %>
              <tr>
                <td><%= line_item.product_sku %></td>
                <td><%= line_item.product_description %></td>
                <td></td>
              </tr>
              <% end %>
            </tbody>
          </table>
        </div>
      </div>
    <% end %>
  <% end %>
<% end %>

订单型号:

class Order < ActiveRecord::Base
  belongs_to :location
  belongs_to :vendor
  has_many :line_items

  accepts_nested_attributes_for :line_items
end

位置模型:

class Location < ActiveRecord::Base
  has_many :orders
end

供应商模型:

class Vendor < ActiveRecord::Base
  has_many :orders
end

LineItem模型:

class LineItem < ActiveRecord::Base
  belongs_to :order
end

我需要以下示例输出:

Vendor A
   Location 1
      Order:
        1. sku:111, description:zzz
        2. sku:222, description:yyy
   Location 2
      Order:
        1. sku:333, description:zzz
        2. sku:444, description:yyy

Vendor B
   Location 1
      Order:
        1. sku:aaa, description:zzz
        2. sku:bbb, description:yyy
   Location 2
      Order:
        1. sku:ccc, description:zzz
        2. sku:ddd, description:yyy

等等。

但是,它会显示所有供应商下所有地点和所有地点的所有订单。

2 个答案:

答案 0 :(得分:0)

如果供应商has_many:位置和位置has_many:orders,那么您可以像这样构建循环:

<% @vendors.each do |vendor| %>
  <h2><%= vendor.name %></h2>

  <% @locations.each do |location| %>
    <h3><%= location.address %></h3>

    <% vendor.orders.where(location_id: location.id).each do |order| %>

    <% end %>
  <% end %>
<% end %>

答案 1 :(得分:0)

首先,您应该更改关联以使层次结构更顺畅。至少位置应该属于供应商和订单belongs_to位置,除非存在这种情况,这不适用于您的业务案例,这使事情变得复杂。

您在每个循环中都获得了所有内容,因为您的实例变量不会像您希望它们被表示一样占据父项。修复关联后,可以从正在迭代的对象中调用子东西:

<% @vendors.each do |vendor| %>
  <h2><%= vendor.name %></h2>
  <% vendor.locations.each do |location| %>
    <h3><%= location.address %></h3>
    <% location.orders.each do |order| %>
      <% order.line_items.each do |line_item| %>
        ...
      <% end %>
    <% end %>
  <% end %>
<% end %>

然而,有一种更简单,更Railsy的方法:

# index.html.erb
<%= render @vendors %>

# views/vendors/_vendor.html.erb
<h2><%= vendor.name %></h2>
<%= render vendor.locations %>

# views/locations/_location.html.erb
<h3><%= location.address %></h3>
<%= render location.orders %>

# views/order/_order.html.erb
<% order.line_items.each do |line_item| %>
  ...
<% end %>

当以这种方式使用render时,Rails将自动迭代关联,默认为每个关联调用部分classname/_classname.html.erb。在这些部分中,Rails自动为对象分配一个局部变量,其名称与partial相同,这就是为什么在_vendor.html.erb内你可以使用vendor变量在当前迭代中调用对象上的方法

您可能希望在查询中使用预先加载来填充@vendor以避免n + 1问题。好处是你可以摆脱@orders@locations等等。