How to handle a Rails query causing massive delays - ruby-on-rails

So I'm using the query below that is then being used as a submenu and it's causing significant loading issues. I've put it in the application_helper for the time being.
def category_level
Connector::Category.includes(:products).group_by(&:parent_category_id)
end
Then it's being displayed on the home page with the following:
<ul class="list-style-upper">
<% category_level[nil].each do |root| %>
<%= render 'products/submenu/category_item', category: root %>
<% end %>
</ul>
Which redirects to
<li class="list-one">
<%= category.name %><p><%= category.products.count %></p>
<% 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>
The issue is that there are typically around 30,000 products. Is there a way to build out the results and store them for display?

Related

create instance variable in erb template

Say I have 2 erb views: a list view and a show view, I want to render the show view inside the list view
list view
<% #vehicles.each do |vehicle| %>
<h2><%= vehicle.type %></h2>
<ul>
<% vehicle.accessories.each do |accessory| %>
<li><% accessory.title %></li>
<% end %>
</ul>
<% end %>
show view
<h2><%= #vehicle.type %></h2>
<ul>
<% #vehicle.accessories.each do |accessory| %>
<li><% accessory.title %></li>
<% end %>
</ul>
the issue is the show view takes an #vehicle instance variable, how can I pass that down from the parent if I was going to nest these and it still shows up as an instance variable, accessed with #vehicle? something like:
<% #vehicles.each do |vehicle| %>
<%= render "show" %>
<% end %>
I guess you might want to make that show view a partial. Something like:
<h2><%= vehicle.type %></h2>
<ul>
<% vehicle.accessories.each do |accessory| %>
<li><% accessory.title %></li>
<% end %>
</ul>
Then you can do something like:
<% #vehicles.each do |vehicle| %>
<%= render "path/to/show_partial", locals: {vehicle: vehicle} %>
<% end %>
Naturally, you'll want to:
use the real path/to/show_partial, whever that happens to be, and
do some eager loading so that you're not doing a whole bunch of N+1 queries.

Sorting in html.erb

This code grabs information from yaml files and outputs them in ascending order (I'm assuming by default). I can't figure out how to code this to reverse the order. Any suggestions? The site is using Middleman and ERB as templating language.
View:
<ul class="app-list">
<% data.apps.each do |app| %>
<% if app[1][:categories][:featured] && app[1][:categories][:script] %>
<li>
<%= partial 'partials/app', locals: { app: app[1] } %>
</li>
<% end %>
<% end %>
</ul>
Try:
<ul class="app-list">
<% data.apps.reverse.each do |app| %>
<% if app[1][:categories][:featured] && app[1][:categories][:script] %>
<li>
<%= partial 'partials/app', locals: { app: app[1] } %>
</li>
<% end %>
<% end %>
</ul>

how to display an item once from a list where that item shows up multiple times in ruby

I've written the code in my .html.erb file but am thinking it might more sense to write it in my controller? This code returns all the names. I'm trying to figure out how to fetch a tag name only once and if a user inputs a tag name that has already been used it does not show up again.
<ul>
<% #pictures.each do |pic| %>
<% pic.tags.each do |tag| %>
<li>
<%= tag.name %>
</li>
<% end %>
<% end %>
</ul>
<ul>
<% #pictures.collect{|x| x.tags.uniq}.flatten.uniq.each do |tag| %>
<li>
<%= tag.name %>
</li>
<% end %>
</ul>
Using Enumerable#flat_map and Array#uniq:
<ul>
<% #pictures.flat_map { |pic| pic.tags.map(&:name) }.uniq.each do |name| %>
<li>
<%= name %>
</li>
<% end %>
</ul>
Example
<ul>
<% #pictures.each do |pic| %>
<% pic.tags.uniq_by(&:name).each do |tag| %>
<li>
<%= tag.name %>
</li>
<% end %>
<% end %>
Use the Array#- method for all items collected that the user enters.
this is relative to how you store the tag values, inside your save method you should make the tags array to be uniq.

content_for shows only in that view, not others

In my activities view I use a content_for like this:
<% content_for :activities do %>
<div id="contentblock">
<div class="content_title general"></div>
<ul id="updates">
<% #activities.each do |activity| %>
<li><%= activity.created_at.in_time_zone.strftime("%d-%m-%Y # %H:%M") %><br /><%= activity.activity %></li>
<% end %>
</ul>
</div>
<% end %>
And in the application layout I want to show this by doing this:
<% if content_for?(:activities) %>
<%= yield :activities %>
<% end %>
However, it only shows if the activities view is active, not in others views. Why is that?

Rails ancestry treemenu help

I am trying to make a simpel treelistmenu with ancestry.
Here is my code in view and it is not working:
<ul>
<% for cat_opg in CatOpg.roots %>
<li> <%= cat_opg.navn %><li>
<% for cat_opg in CatOpg.children %>
<li> <%= cat_opg.navn %><li>
</ul>
<% end %>
</ul>
<% end %>
And my controller:
def liste
#cat_opg = CatOpg.find(:all)
end
I want to make this simpel tree menu as:
Root
-children
Root
-children
I dont know what i am doing wrong.
PS: I am a rails beginner
First of all, you are getting to model in view, not to local variable.
Second, you're rewriting variable.
It should be something like this:
<ul>
<% cat_opg.roots.each do |cat_opg_root| %>
<li> <%= cat_opg_root.navn %><li>
<% cat_opg_root.children each do |cat_opg_child| %>
<li> <%= cat_opg_child.navn %><li>
</ul>
<% end %>
</ul>
<% end %>
Alex thank you for your answer.
Now it works
Controller: #cat_opg = CatOpg
And the view:
<ul>
<% #cat_opg.roots.each do |cat_opg_root| %>
<li> <%= cat_opg_root.navn %></li>
<% unless cat_opg_root.children.empty? %>
<ul>
<% cat_opg_root.children.each do |cat_opg_child| %>
<li> <%= cat_opg_child.navn %></li>
<% end %>
</ul>
<% end %>
<% end %>
</ul>

Resources