如何在Rails中设置双向动态表

时间:2013-02-04 05:12:49

标签: ruby-on-rails

我可能在这里忽略了一个简单的方法,但是在2轴上编码动态表的最佳方法是什么。我正在使用Rails 3.2

例如,假设我有以下模型

class Region
  has_many :shops
end

class Shop
  has_many :sales
  has_many :products, through: :sales
end

class Sale
  belongs_to :shop
  belongs_to :product
end

class Product
  has_many :sales
  has_many :shops, through: :sales
end

在区域展示视图中,我想显示一个表格,列出商店列标题,商品列为行标题,并计算每个单元格的平均值Sale.price

我陷入混乱的嵌套块,计算出的值似乎与我的预期不符。

是否有一种简单的Rails-y方式可以做这样的事情?或者任何人都可以推荐我可以学习的任何示例代码

我的实际模型比我描述的要复杂得多,我想知道是否应该花时间处理我的代码进行调试,或者我是否应该遵循更简单的方法。这似乎是一个相当普遍的要求。

修改

我的代码示例

#views/regions/show.html.erb
<table>
  <tr>
    <th>Shop Name</th>
    <% for product in @region.products.uniq %>
      <th><%= product.name%></th>
    <% end %>
  </tr>
  <% for shop in @region.shops.uniq %>
    <tr>
      <td><%= shop.name %></td>
      <% for product in @region.products.uniq %>
        <td><%= product.sales.average(:price, conditions: ['sale.shop_id = ?', shop], :include => :sale) %></td>
      <% end %>
    </tr>
  <% end %>
</table>

1 个答案:

答案 0 :(得分:1)

您可以尝试这样计算每家商店的平均销售额。

Shop.joins(:sales).average(:price, group: :product_id)

这将产生一个散列,其中键是产品ID,值是该产品的平均值。如果您想显示更多详细信息而不仅仅是产品ID,可以将:group选项更改为(使用postgre)

Shop.joins(sales: :product).average(:price, group: "product_id || ' - ' || products.name")

更新:在问题上使用视图模板(警告,这对一大组记录来说会很慢)

#views/regions/show.html.erb
<table>
  <tr>
    <th>Shop Name</th>
    <% @region.products.each do |product| %>
      <th><%= product.name%></th>
    <% end %>
  </tr>
  <% @region.shops.each do |shop| %>
    <tr>
      <td><%= shop.name %></td>
      <% shop.products.each do |product| %>
        <td><%= product.sales.where(shop_id: shop.id).average(:price) %></td>
      <% end %>
    </tr>
  <% end %>
</table>

更新:这可能是一种更快捷的方式

# controller
@shops = @region.shops
@products = Product.joins(:shops).where(shops: { region_id: @region.id })
@averages = Sale.joins(:shop).average(:price, group: ['shops.id', 'shops.name', 'sales.product_id])

# view
<tr>
  <th>Shop Name</th>
  <% @products.each do |product| %>
    <th><%= product.name%></th>
  <% end %>
</tr>
<% @shops.each do |shop| %>
  <tr>
    <td><%= shop.name %></td>
    <% @products.each do |product| %>
      <td><%= @averages[[shop.id, shop.name, product.id]] || 0 %></td>
    <% end %>
  </tr>
<% end %>