I am iterating over a set of objects in Ruby on Rails like so :
<% #subject.Association.each do |horse| %>
<tr>
<td>
<%= horse['Name'].to_s %>
<%= horse['Size'] %>
</td>
</tr>
<% end %>
The horse object has a date field, called dateRode.
I would like to order by this field.
I am not a ruby developer, but I tried a number of ways to do this resulting in only syntax errors e.g
<% subject.association.each do |horse|-> { order by "dateRode" DESC } %>
How can I do this in my code without editing ActiveRecords etc?
You can order collection with order method like this:
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
<tr>
<td>
<%= horse['Name'].to_s %>
<%= horse['Size'] %>
</td>
</tr>
<% end %>
Try to replace this:
<% #subject.Association.each do |horse| %>
with
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
Hoping that it would help you.
<% subject.association.each do |horse|-> { order by "dateRode" DESC } %>
The above is a mix of erb and sql which isnt going to work.
The best way to do it is to create a scope in the model which is called by the controller.
model
def self.order_by_date_rode
Model.includes(:association).order("associations.dateRode desc")
end
where Model is the name of your model and association is the name of the association you want to order by.
controller method
def some_method
#subject = Model.order_by_date_rode
end
A less recommended way is to do the sorting in the view
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
the another way is that you can set a default scope for ordering of the association model like below
class Association < ActiveRecord::Base
default_scope { order('dateRode DESC') }
end
so when you do <% #subject.Association it will automatically sort
Related
i want to achieve a nested loop without duplicates in a have and belongs to many relationship
i have a model 'campaign' and for each campaign i also have campaign data.
i want to display each campaign with its campaign data in a table. (nested)
#campaigns = current_user.campaigns
<% #campaigns.each do |item| %>
<% i = item.campaign_data %>
<% i.each do |cdata| %>
<%= cdata.date %>
<tr>
<td>
<%= item.name %>
</td>
<td>
<%= cdata.date %>
</td>
<td>
</td>
</tr>
<% end %>
<% end %>
my problem is that my campaigns get duplicated.
I want to achieve something like this:
Each campaign is listed in the table with its corresponding campaign_data directly below it, and if no campaign_data is left the next loop begins with the next campaign - is this possible?
best regard
You might be getting duplicated campaigns as you are using <%= item.name %> inside the <% i.each do |cdata| %> loop. So, if one campaign has 4 campaign_datas you will see the campaign name 4 times.
You should use naming conventions properly, if the campaign has many data campaign_data then you should specify so in association i.e. has_many :campaign_datas
Also, the Following code should be in the controller
#campaigns = current_user.campaigns.include(:campaign_datas)
Note:- I used include to avoid n + 1, please read here.
In view
<% for campaign in #campaigns %>
<% next if #campaigns.campaign_datas.blank? %>
<tr>
<td><%= item.name %></td>
</tr>
<% for campaign_data in #campaigns.campaign_datas %>
<tr>
<td><%= campaign_data.date %></td>
</tr>
<% end %>
<% end %>
Note:-
<% next if #campaigns.campaign_datas.blank? %> line is used to skip the campaign if it has no campaign data.
Below code is showing parametersname from DataModel table(data base).I have one more table DataModelDevices which has parameter_name column.I want to show parameter_name as well in same row in UI. How to join one more table in rails?
I have tried below code but not working.
<% DataModel.preload(:devices,:revision).where(device: true).where("parametersname NOT LIKE '%.'").where("parametersname LIKE '%{i}%'").order(:id).each do |parameter| %>
<tr onclick="javascript:showRowDeviceTest(this);">
<% DataModelDevices.all.each do |parameterhard| %>
<td style="word-break:break-all;">
<%= parameter.parametersname%>
<%= parameterhard.parameter_name%>
</td>
<% end %>
<% end %>
Actual Working Code
<% DataModel.preload(:devices,:revision).where(device: true).where("parametersname NOT LIKE '%.'").where("parametersname LIKE '%{i}%'").order(:id).each do |parameter| %>
<tr onclick="javascript:showRowDeviceTest(this);">
<td style="word-break:break-all;">
<%= parameter.parametersname%>
</td>
</tr>
<% end %>
you should add association in the models In DataModel:
has_many :data_model_devices
In DataModelDevice:
belongs_to :data_model
You can join with the following code whatever you want:
DataModel.joins(:data_model_devices).
select('data_model_devices.parameter_name, data_models.*').load
So i have this in my view
<% #events.each do |event| %>
<% if event.eventcomplete %>
<% else %>
<tr>
<td colspan="7">
<p>
No Events could be found.
</p>
</td>
</tr>
<% end %>
This is on my search results page,
However what im wanting if there is no eventcomplete, Just display one No events found,
At the moment i'm gettting around 100 events found but, None of them are complete. So i'm getting around 100 "No Events could be found"
Thanks for any help
Sam
I don't know what your code looks like, but something smells wrong to me that you're filtering by eventcomplete in your view both for determining which rows to display and for whether or not to show your "No results" message. Presumably you will later want to do other things using this collection (like pagination), so I'd suggest filtering the collection in the controller:
# controller code
#in_progress_events = #events.where(eventcomplete: false)
Once the collection is being properly filtered before it hits the view, check out the points in this answer for tips on display: Rails: An elegant way to display a message when there are no elements in database
Your code is missing an <% end %> tag.
<% #events.each do |event| %>
<% if event.eventcomplete %>
[insert view code to show if event.eventcomplete is true]
<% else %>
<tr>
<td colspan="7">
<p>
No Events could be found.
</p>
</td>
</tr>
<% end %>
<% end %>
Actually the code is doing exactly what it should do,
your html Block was defined in your each block, this is why it got raised 100 times.
I just fixed it with Helper Variables, but it is just a workaround
You should make use of more static methods in your models, just define it
Please make sure your business logic holds place in your models:
Fat models, Thin Controllers/Views
this should work
<% #there_is_no_eventcomplete = false %>
<% #events.each do |event| %>
<% if event.eventcomplete %>
#there_is_no_eventcomplete = true
<% end %>
<% end %>
<% if #there_is_no_eventcomplete == false %>
<tr>
<td colspan="7">
<p>
No Events could be found.
</p>
</td>
</tr>
<% end %>
You want to use a scope on your model which you can then call in the controller. I'm not sure how you've set up your model or how you determine if an event is completed, so lets assume you have a boolean attribute completed on your model:
event.rb
class Event
def self.completed
where(complete: false)
end
end
controller
#events = Event.completed
view
<% unless #events.nil?
<% #events.each do |event|%>
// your code
<% end %>
<% else %>
// your code
<% end %>
I came accross something strange when trying to create friendly URLs.
I have an item model which has:
def to_param
"#{id}-#{name}".parameterize
end
This makes my item URLs contain the "ID" and "name" just fine:
www.domain.com/items/ID-name
I also have a category model (item belongs to category and user models) where I have the same def to_param as above but the category URLs stay "unfriendly" no "name" included:
domain.com/categories/ID
I have name column in category table and it has values.
I also use ancestry for the category model. Maybe has_ancestry is causing the issue?
I tried below but no luck:
def to_param
[id, name.parameterize].join("-")
end
Thanks for any advice!
Papirtiger's comment lead me to the solution.
The problem was I had links like:
<% #category.children.in_groups_of(4, false) do |childs| %>
<tr>
<% for categories in childs %>
<td>
<%= link_to "../categories/#{categories.id}" do %><%= categories.name %><% end %></td>
<% end %>
</tr>
Beginners solution. :)
Removed the ugly part and now it works:
<% #category.children.in_groups_of(4, false) do |childs| %>
<tr>
<% for categories in childs %>
<td><%= link_to categories do %><%= categories.name %><% end %> (<%= Item.where(:category_id => categories.id).count %>)</td>
<% end %>
</tr>
I have two models, with those associations:
class Product < ActiveRecord::Base
has_many :side_orders
has_many :garnishes, :through => :side_orders
attr_accessible :garnishes_number
end
Garnishes are also products, so it's a self-joined association:
class SideOrder < ActiveRecord::Base
belongs_to :product
belongs_to :garnish, :class_name => "Product", :foreign_key => "garnish_id"
attr_accessible :list_number
end
One product may have many lists of garnishes (so that customer may choose different garnishes when they order one product). It's one list per choice. One product don't have more than "garnishes_number" lists of choices.
In my application, in the admin part, I have to do something like this:
<% Product.all.each do |product| %>
<% for i in 0..(product.garnishes_number - 1) %>
Lists of garnishes:
<%= product.garnishes.where("side_orders.list_number = ?", i) %> <br />
<% end %>
<% end %>
It's just an example... Problem is that Rails do one query per value of "i", so if a product has 8 lists, Rails will perform 8 queries to the database... And when there are more than hundreds of products, it becomes really slow...
Is there a way to optimize such a query? Includes doesn't seem to work... If anyone has any idea or maybe a different logic, don't hesitate to answer.
[Edit] The fact that I want to access each list of garnishes is important because I want them to appear in a table in such way:
<table>
<thead>
<td>Product</td>
<td>List of garnishes </td>
</thead>
<tbody>
<% Product.all.each do |product| %>
<% for i in 0..(product.garnishes_number - 1) %>
<tr>
<td>product.name</td>
<td>
List number <%= i %>:
<%= product.garnishes.where("side_orders.list_number = ?", i) %>
</td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
I didn't put that in the first place, because I didn't want my question to be too long... But, I think I should have wrote it down already so that my problem could be more understandable... Sorry ^^'
Thanks a lot!
Kulgar.
you can do it by following way
<% Product.all.each do |product| %>
<% temp = Array.new %>
<% for i in 0..(product.garnishes_number - 1) %>
<% temp.push(i) %>
<%end%>
Lists of garnishes:
<%= product.garnishes.where("side_orders.list_number in(?)", temp ) %> <br />
<% end %>
This will call where query only one time for each product