【问题标题】:How to set up a 2-way dynamic table in Rails如何在 Rails 中设置 2-way 动态表
【发布时间】:2013-02-04 17:40:39
【问题描述】:

我可能在这里忽略了一种简单的方法,但是编写在 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

在 Region show 视图中,我想显示一个表格,在列标题中列出 Shops,在行标题中列出 Products,并计算每个单元格的平均 Sale.price

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

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

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

编辑

我的代码示例

#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>

【问题讨论】:

    标签: ruby-on-rails


    【解决方案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 %>
    

    【讨论】:

    • 您好,jvnil,感谢您提供这条有用的线路。不过,我仍然在努力了解如何将计算构建到表格中(我希望我很慢)。我已经用我拥有的代码更新了我的问题。它不能按原样工作,即使是这种方法的性能也不理想。感谢任何指针帮助我想象这是如何工作的。
    • 嘿@AndyHarvey,我已经更新了我的答案。如果您只需要显示文本,您可以使用我的第一个答案,这样您就不会创建更快的活动记录对象。如果您需要访问商店和产品,请使用第二个。
    • 太好了,我知道我的查询很密集!同意您的观点,性能可能会受到影响。有没有更好的方法来做到这一点,以便最大限度地减少数据库交互?或者这已经是最好的了?
    猜你喜欢
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    相关资源
    最近更新 更多