来自不同表的Rails显示名称属性以及来自联接表的计数

时间:2018-11-08 17:44:18

标签: ruby-on-rails

我有下表:产品,类别,ProductCategory。

我试图在分支结构中显示以下内容:

Accessories - 5,000
 Men's Watches - 2,000
  Tag Huer - 1,000
  Samsung - 1,000
 Women's Watches - 3,000

我遇到的问题是我的查询使应用程序变慢。我有以下查询:

def category_level
 Connector::Category.includes(:products).group_by(&:parent_category_id)
end

然后在我看来,我有以下内容:

<ul class="list-style-upper">
 <% category_level[nil].each do |root| %>
  <%= render 'products/submenu/category_item', category: root %>
 <% end %>
</ul>

哪个加载到:

<li class="list-one">
 <a href="#"><%= category.name %><p><%= category.products.count %></p></a>
 <% if category_level[category.id].present? %>
  <ul class="list-style-upper-sub">
    <% category_level[category.id].each do |child| %>
      <%= render 'products/submenu/category_item', category: child %>
    <% end %>
  </ul>
 <% end %>
</li>

它会显示,但是要花很长时间,因为它会打到“产品”表并遍历所有产品。因此,为了简化起见,我想我只需点击ProductCategory页面即可获得以下内容的计数:

def level_up
 @category_counts = Connector::ProductCategory.group(:category_id).count
end

这实际上只会显示以下内容:

{54 => 11, 29 => 14, 51 => 19, 10 => 3202}

虽然是,但是10代表配件,我希望看到配件-3,202。

是否有任何建议清除名称属性?

1 个答案:

答案 0 :(得分:1)

提供的模型如下所示:

class Category < ApplicationRecord
  has_many :product_categories
  has_many :products, through: :product_categories
end

class ProductCategory < ApplicationRecord
  belongs_to :product
  belongs_to :category
end

class Product < ApplicationRecord
  has_many :product_categories
  has_many :categories, through: :product_categories
end

可以通过联接并选择联接表的计数来获得相关项目的计数:

Category.left_outer_joins(:product_categories)
  .select('categories.*, count(product_categories.*) AS product_count')
  .group('categories.id')

.left_outer_joins已在Rails 5中添加。对于早期版本,请使用:

.join('LEFT OUTER JOIN product_categories ON product_categories.category_id = category.id')

如果您不关心没有任何产品的类别,也可以使用.joins(:product_categories)

该计数将在每个记录上显示为.product_count

这也可以通过添加计数器缓存来实现:

class ProductCategory < ApplicationRecord
  belongs_to :product
  belongs_to :category, counter_cache: true
end

class AddProductCategoriesCountToCategories < ActiveRecord::Migration[5.2]
  def change
    add_column :categories, :product_categories_count, :integer, default: 0
  end
end

这会将计数存储在categories.product_categories_count中。当您的读取操作多于写入操作时,最好使用计数器缓存。