Sort association models in Rails 3? - ruby-on-rails

Menu has_many :dishes.
I want to sort the dishes by Dish.number.
Currently in my view it looks like:
<table class="menu">
<% #menu.dishes.each do |dish| %>
<div class="dish">
<tr>
<td>
<div class="dish_div dish_name">
<% if #menu.name != 'Övrigt' && #menu.name != 'Box to go' %>
<span class="dish_name"><%= "#{dish.number}. #{dish.name}" %></span>
<% else %>
<span class="dish_name"><%= "#{dish.name}" %></span>
<% end %>
<% if dish.strength_id == 2 %>
<%= image_tag('chili.png') %>
<% elsif dish.strength_id == 3 %>
<%= image_tag('chili.png') %>
<%= image_tag('chili.png') %>
<% elsif dish.strength_id == 4 %>
<%= image_tag('chili.png') %>
<%= image_tag('chili.png') %>
<%= image_tag('chili.png') %>
<% end %>
</div>
<div class="dish_div"><%= "#{dish.description}" %></div>
<div class="dish_div dish_price"><%= "#{dish.price} kr" %></div>
</td>
</tr>
</div>
<% end %>
</table>
How do I do that?
Should it be in the view or controller?
Thanks

Neither! :) --- do it in your model definitions
If you always want to order on strength:
class Menu
has_many :dishes, :order=>'strength_id DESC'
end
class Dish
belongs_to :menu
end
Otherwise, just order in the view:
<% #menu.dishes.sort_by{|dish| dish.strength_id}.each do |dish| %>

In your controller:
def list
#dishes = #menu.dishes.all(:order => :number)
end
In your view:
<% #dishes.each do |dish| %>

I'm not sure if I understood what you're trying to do, but … to iterate the dishes sorted by their number attribute, you just need to use the :order option on the dishes:
<% #menu.dishes.all(:order => :number).each do |dish| %>
...
<% end %>

You can use the order method:
<% #menu.dishes.order(number: :asc).each do |dish| %>

Related

One to many relationship fom_for take the last 3 from all the model attributes

I have one to many relationship(oferta have many sigs) and I want to show the last three sigs from all the oferta
I tried this code but it show the last 3 sigs from each oferta
In home index.erb
<% #oferta.each do |o| %>
<% if o.sigs.exists? %>
<% for item in o.sigs.order("created_at asc").last(3).each %>
<div class="col-md-4 col-sm-4">
<div class="coll">
<br>
<%= link_to item do %>
<%= image_tag item.image.url(), skip_pipeline: true ,id: "img",height: "200px"%>
<% end %>
<h4><%=link_to item.name,item %></h4>
<p id="comment"><%= item.comment %></p>
<%= link_to "read more..", item %>
<p id="price"><%= item.price %></p>
</div>
</div>
<% end %>
<% end %>
<% end %>
In the controller
def index
#oferta = Ofertum.unscoped.first(3)
end
In ofertum model
has_many :sigs
In sig model
belongs_to :ofertum
You can do it in both ways,
#last_3_sigs = Sigs.last(3)
for getting latest records first use this
#last_3_sigs = Sig.order(created_at: :desc).limit(3)

Indent every child of a depth first search (ruby on rails)?

I am new to rails, and I was wondering if there was a simple (or not simple) way to indent every child of a DPS?
I have a model called "Comment" that has_many :comments and belongs_to :comment. In my view I've implemented a DPS to display each comment and each comment on that comment, and each comment on that comment, etc.
My code looks like this:
<div class=feed>
<% #comments.each do |comment| %>
<% if comment.comment_id == nil # display all original comments %>
<!-- subject -->
<div class="subject">
<%= comment.subject %>:
</div>
<!-- create array of replies -->
<% replies = Array.new %>
<% replies.push(comment) %>
<% while replies.any? %>
<% reply = replies[0] %>
<% replies.delete_at(0) %>
<!--- name -->
<div class="comment">
<%= User.find(reply.user_id).name %>
<!-- comment -->
<%= reply.body %>
<% if user_signed_in? %>
<%= link_to "reply", new_comment_comment_path(reply.id) %>
<% end %>
</div>
<% reply.comments.each do |further_replies| %>
<% replies.push(further_replies) %>
<% end %>
<br>
<% end %>
<br>
<% end %>
<% end %>
</div>
where I push each comment onto "replies" and visit each reply one by one.
Is there a good way to indent each child comment?
Thanks!
You can use act_as_tree structure, in that case your model will be like -
class Comment
has_many :replies, class_name: 'Comment', foreign_key :comment_id
belongs_to :user
end
Your html code will be very simple in that case like
<div class=feed>
<% #comments.each do |comment| %>
<div class="subject">
<%= comment.subject %>:
</div>
<% comment.replies.each do |reply| %>
<div class="comment">
<%= reply.user..name %>
<%= reply.body %>
<% if user_signed_in? %>
<%= link_to "reply", new_comment_comment_path(reply.id) %>
<% end %>
</div>
<br>
<% end %>
<br>
<% end %>
</div>
I figured out a different approach that worked well. I implemented a recursive depth first search in "CommentsController" that returned a hash of { comments => amount_to_indent }, where comments are in the order that they were visited. In the view file iterated though the hash, using comment and amount_of_indent where appropriate.
class CommentsController < ApplicationController
def index
#comments = Comment.all
# depth first search
#visited = Hash.new
#comments.each do |comment|
if !comment.comment_id # has not parent comment
indent = 0
comment_array = DFS(comment, #visited, indent)
end
end
end
def DFS(comment, visited, indent)
visited[comment] = indent # add elements in order in which they are visited
comment.comments.each do |reply|
DFS(reply, visited, indent + 4)
end
visited
end
And in the view file:
<div class="feed">
<% #visited.each do |reply, indent| %>
<!-- display subject of all parent comments -->
<div class="subject">
<% if !reply.comment_id? %>
<%= reply.subject %>:
<% end %>
</div>
<!--- name and content -->
<div class="comment">
<!-- preceed comment with indent -->
<%= raw(('&nbsp') * indent) %>
<%= User.find(reply.user_id).name + ":" + reply.body %>
<% if user_signed_in? %>
<%= link_to "reply", new_comment_comment_path(reply.id) %>
<!--%= link_to 'delete', response, method: :delete, data: { confirm: 'Are you sure?' } %-->
<% end %>
</div>
<% end %>
</div>
If anyone runs into the same issue I did!

Can't get shared filters in home view to work in spree demo

In the spree demo (latest version), I tried to use shared/filters instead of shared/taxonomies in views/spree/home/index.html.erb:
<% content_for :sidebar do %>
<div data-hook="homepage_sidebar_navigation">
<%#= render :partial => 'spree/shared/taxonomies' %>
<%= render :partial => 'spree/shared/filters' %>
</div>
<% end %>
I get the filters (All Taxons), but when I pick some, like Bags and T-Shirts and click on search, the filter doesn't work.
I didn't change anything in shared/filters:
<% filters = #taxon ? #taxon.applicable_filters : [Spree::Core::ProductFilters.all_taxons] %>
<% unless filters.empty? %>
<%= form_tag '', :method => :get, :id => 'sidebar_products_search' do %>
<%= hidden_field_tag 'per_page', params[:per_page] %>
<% filters.each do |filter| %>
<% labels = filter[:labels] || filter[:conds].map {|m,c| [m,m]} %>
<% next if labels.empty? %>
<div class="navigation" data-hook="navigation">
<h6 class="filter-title"> <%= filter[:name] %> </h6>
<ul class="filter_choices">
<% labels.each do |nm,val| %>
<% label = "#{filter[:name]}_#{nm}".gsub(/\s+/,'_') %>
<li class="nowrap">
<input type="checkbox"
id="<%= label %>"
name="search[<%= filter[:scope].to_s %>][]"
value="<%= val %>"
<%= params[:search] && params[:search][filter[:scope]] && params[:search][filter[:scope]].include?(val.to_s) ? "checked" : "" %> />
<label class="nowrap" for="<%= label %>"> <%= nm %> </label>
</li>
<% end %>
</ul>
</div>
<% end %>
<%= submit_tag Spree.t(:search), :name => nil %>
<% end %>
<% end %>
Any ideas why?

erb block not looping

I'm trying to generate results for a webstore using this erb block and I want 4 images per row, but right now it is only generating one image per row. Any advice would be highly appreciated
<% n = 4 %>
<% #products.each do |product| %>
<div class="row-fluid">
<% if (n%4 == 0) %>
<% end %>
<div class="span3">
<%= link_to image_tag(product.images.order(:placement).first.image.url(:medium)), product if product.images.present? %>
<p class="text-center"><%= link_to product.name, product %></p>
</div>
<% if (n%4 == 3) %>
<% end %>
<% n += 1 %>
</div>
<% end %>
Ruby will break it into groups of four for you using Enumerable#each_slice:
<% #products.each_slice(4) do |row| %>
<div class="row-fluid">
<% row.each do |product| %>
<div class="span3">
<%= link_to image_tag(product.images.order(:placement).first.image.url(:medium)), product if product.images.present? %>
<p class="text-center"><%= link_to product.name, product %></p>
</div>
<% end %>
</div>
<% end %>

If Condition in each do Rails

Hi i need to print out just the candidates where active is == 0 here is my code in the view.
I can print if active is yes or no.. But in the each do loop i just want to print the active candidates.
So how can i add the condition to my each do loop, thanks.
<% #candidates.each do |candidate| %>
<div id="candidateper">
<div class="avatth" ><div class="avat_min">
<% if candidate.avatar.present? %>
<%= link_to (image_tag candidate.avatar.url(:thumb)), (candidate_path(candidate)) %>
<% else %>
<%= link_to (image_tag ("espanol/playersample.png")), (candidate_path(candidate)) %>
<% end %>
</div></div>
<div class="nameth"><%= candidate.name %></div>
<div class="activeth"><%= candidate.active ? t('generales.yess') : t('generales.noo') %></div>
<div class="generalth">
<% if candidate.user.purchased_at.present? %>
<%= candidate.user.purchase_defeated? ? t('generales.defeated') : t('generales.active') %>
<% else %>
<%= t('generales.noo') %>
<% end %>
</div>
<div class="actionsth"><%= link_to t('generales.show'), candidate_path(candidate) %>
<% if current_user.user_type == 'admin' %>
<%= link_to t('generales.delete'), candidate_path(candidate), method: :delete, data: { confirm: t('generales.delete_candidate_confirm') } %>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
I`ve tried this
no luck syntax error on all my ideas :P
If candidate.active is actually a boolean then you could say:
<% #candidates.reject(&:active).each do |candidate| %>
...
<% end %>
If #candidates is actually an ActiveRecord::Relation then you could probably say:
<% #candidates.where(:active => false).each do |candidate| %>
...
<% end %>
to avoid pulling a bunch of stuff out of the database when you don't want it.
If active is actually a number (inside the database and outside the database) then you could say:
<% #candidates.select(&:zero?).each do |candidate| %>
...
<% end %>
or
<% #candidates.where(:active => 0).each do |candidate| %>
...
<% end %>

Resources