I have two cases where it takes a lot of time to load pages, and I'm not sure how to make database calls faster when I started with RoR recently.
Case A
I am trying to show the categories of roots (using the pedigree pearl) and the number of providers that are associated with any of these root categories. Only 15 categories of roots.
The result looks something like this:
suppliers.html.erb
<% Category.roots.each do |category| %>
<li class="pointer txt-hover-grey mili-margin-bottom">
<span class="micro-margin-right">
<%= link_to category.name, category_suppliers_path(category), :title => category.name %>
</span>
<span class="txt-alt">
(<%= category.suppliers_count_active %>)
</span>
</li>
<% end %>
category.rb
def suppliers_count_active
self.suppliers.where(:active => true).pluck(:id).count
end
Case B (Ancestral Gem)
(, eshop). 15 ( 0), 3 ( 45), 5 ( 225). subsub .
:
categories_menu.html.erb
<div class="content no-padding padding-static relative table menu-nr">
<!-- root_categories -->
<% Category.includes(:image, :products).serializable.each do |root| %>
<div class="table-center container-center full-h categories-trigger">
<%= link_to Category.find(root['id']).category_link, :title => root['name'] do %>
<div class="uppercase full-h size-tiny semi-bold txt-hover-main_light semi-padding-top semi-padding-bottom">
<%= root['name'] %>
</div>
<% end %>
<div class="categories-hide categories-dropdown shadow z-1000 bg-white txt-black size-tiny">
<div class="table full-w inwrap-dropdown">
<div class="cell">
<div class="table dropdown-left">
<%
children_sorted = root['children'].sort_by { |child| child['products_sum_count'] }.reverse!.first(3)
children_sorted.each do |cat| %>
<div class="cell container-left">
<div class="table">
<div class="cell container-top">
<div class="mili-margin-left mili-margin-right">
<% cat2 = Category.find_by(:id => cat['id'])
if !cat2.image.blank? %>
<%= image_tag(cat2.image.image.url(:small), :title => cat2.image.title, :alt => cat2.image.title, :class => "img-category") %>
<% end %>
</div>
</div>
<div class="cell">
<h5 class="mili-margin-bottom">
<%= link_to "#{cat['name']}", Category.find(cat['id']).category_link, :title => cat['name'] %>
</h5>
<div class="txt-grey_dark semi_bold mili-margin-bottom">
<%
# cat_children = cat.children.includes(:products)
cat['children'].first(7).each do |sub_cat|
%>
<%= link_to Category.find(sub_cat['id']).category_link, :title => sub_cat['name'], :class => "block txt-hover-grey micro-margin-bottom" do %>
<%= "#{sub_cat['name']}" %> <span class="txt-alt"><%= "(#{sub_cat['products_sum_count']})" %></span>
<% end %>
<% end %>
</div>
<%= link_to "Další kategorie >", Category.find(cat['id']).category_link, :class => "semi-margin-top block txt-alt txt-hover-alt_dark" %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="cell bg-grey_light semi-padding-left">
<div class="table">
<div class="cell container-left">
<div class="mili-margin-left mili-margin-right">
<h5 class="txt-alt mili-margin-bottom">
<%= t(:menu_suppliers_title) %>
</h5>
<%
suppliers = Supplier.joins(:categories).where(:active => true, categories: { :id => root['id'] }).last(3)
suppliers.each do |supplier|
%>
<% cache supplier do %>
<div class="table relative mili-margin-bottom">
<div class="cell inline relative wrap-shop">
<div class="absolute-center-nr center inwrap-shop inwrap-shop-rohlik btn border">
<%= link_to supplier_path(supplier), :title => "#{t(:menu_suppliers_link_title)} #{supplier.name}" do %>
<%= image_tag(supplier.image.image.url(:small), :alt => supplier.image.title) if !supplier.image.blank? %>
<% end %>
</div>
</div>
<div class="col inline semi-margin-left-nr">
<div class="table txt-avatar-small full-w">
<div class="table-center">
<%= link_to supplier.name, supplier_path(supplier), :title => "#{t(:menu_suppliers_link_title)} #{supplier.name}", :class => "semi-bold block micro-margin-bottom" %>
<div class="txt-alt">
<%= t(:homepage_suppliers_logo_text, :commission => supplier.commission_donated, :commission_type => supplier.commission_type ) %>
</div>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
<span class="block txt-alt txt-hover-alt_dark half-margin-bottom">
</span>
<%#= link_to t(:menu_suppliers_link_others), category_suppliers_path(:id => root['id']), :title => t(:menu_suppliers_link_others), :class => "block txt-alt txt-hover-alt_dark half-margin-bottom" %>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="categories-hide wrap-categories-arrow relative">
<div class="categories-arrow absolute z-1000">
</div>
</div>
</div>
<% end %>
</div>
category.rb
def self.serializable
Category.includes(:translations).where(categories: {:active => true, :ancestry_depth => 0..2 }, category_translations: {:locale => I18n.locale.to_s} ).arrange_serializable(:order => 'category_translations.name')
end
def category_link
category_path(self)
end
. .
,
Miroslav
1:
NewRelic. B, dalli memcache identity_cache. , .
2:
:
result = Benchmark.ms { Category.includes(:translations).where(categories: {:active => true, :ancestry_depth => 0..2 }, category_translations: {:locale => I18n.locale.to_s} ).arrange_serializable(:order => 'category_translations.name') }
=> 7207.116272300482
( 1000) , .
, .
3
postgres.
CategoryTranslation
create_table "category_translations", force: :cascade do |t|
t.integer "category_id", null: false
t.string "locale", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
add_index "category_translations", ["category_id"], name: "index_category_translations_on_category_id", using: :btree
add_index "category_translations", ["locale"], name: "index_category_translations_on_locale", using: :btree
create_table "categories", force: :cascade do |t|
t.string "name"
t.boolean "active", default: false
t.integer "level"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ancestry"
t.string "mapping"
t.integer "products_count", default: 0, null: false
t.integer "products_sum_count", default: 0
t.integer "ancestry_depth", default: 0
t.string "category_link"
t.string "image_link"
end
add_index "categories", ["ancestry"], name: "index_categories_on_ancestry", using: :btree