how to get key in ruby on rails .each loop - ruby-on-rails

In laravel I am use to being able to access the key in a loop. In rails I cannot find answer to how to get that from the loop.
Standard loop like so
<% #subjects.each do |subject| %>
<div class="col-md-6 subjectColumn">
<div class="subjectBox subjectBox-<%= key %>">
<h2><%= subject.title.capitalize %><h2>
<p><%= subject.description %></p>
View courses<i class="fa fa-angle-right"></i></h2>
</div>
</div>
<% end %>
I want to add the integer for the key in the code above. I have tried...
<% #subjects.keys.each do |key, subject|
...and other various things I found here and elsewhere but nothing worked. The above code created an error. Most of the things I found just did not give any number. Any help with this would be greatly appreciated. I feel I probably just have not got the syntax quite correct or something.

Use with_index:
<% #subjects.each.with_index(1) do |subject, index| %>
<div class="col-md-6 subjectColumn">
<div class="subjectBox subjectBox-<%= index %>">
<h2><%= subject.title.capitalize %><h2>
<p><%= subject.description %></p>
View courses<i class="fa fa-angle-right"></i></h2>
</div>
</div>
<% end %>

Related

Rails Helper create unintended Array ouput

I have created a rails helper method, So far so good the only problem is it created an unexpected array ouput.
I did try the key value pair using the each method but the array still there.
I'm trying to figure it out how to remove the unexpected array
My application_helper.rb
def bid_items(origin, destination)
item = Item.where(item_deliver_from: origin).where(item_deliver_to: destination).where(shopper_id: current_user)
end
My search_results.html.rb
<%= bid_items(trip.origin, trip.destination).each do |item| %>
<div class="card border-0">
<%= image_tag item.cover_image_url(:cover_image_medium), class: "card-img-top" %>
<div class="card-body">
<h5 class="card-title"><%= item.name %></h5>
</div>
</div>
<% end %>
Though I got the intended results still, there's an unexpected array
check the image
I just want to remove this area
See Red X
Remove = sign from <%= bid_items(trip.origin, trip.destination).each do |item| %>
So, make it <% bid_items(trip.origin, trip.destination).each do |item| %>

Splitting record set in Rails for display purposes in menu

I'm trying to split my records in half for display in my menu. The menu is two columns (col-md-4) but the methods I'm using with ODD number of records, puts the larger number on the wrong side (last_half) of my menu. What am I missing?
Menu
<div class="col-md-4">
<ul>
<li class="mega-menu-title">Products</li>
<% first_half(#menu_products).each do |product| %>
<li>
<%= link_to product_path(product) do %>
<span class="text-yellow"><%= product.name %></span> <%= product.subtitle %>
<% end %>
</li>
<% end %>
</ul>
</div>
<div class="col-md-4">
<ul>
<li class="mega-menu-title"> </li>
<% last_half(#menu_products).each do |product| %>
<li>
<%= link_to product_path(product) do %>
<span class="text-yellow"><%= product.name %></span> <%= product.subtitle %>
<% end %>
</li>
<% end %>
</ul>
</div>
<div class="col-md-4">
<!--- non-related code in last column in menu --->
</div>
Application Helper
def first_half(list)
list[0...(list.length / 2)]
end
def last_half(list)
list[(list.length / 2)...list.length]
end
You can use the following:
list.first((list.length/2).ceil) # will convert 1.5 to 2
And
list.last((list.length/2).floor) # will convert 1.5 to 1
The issue you had is that [7,8,9][3/2] returns 8, and the logic 3/2 (list.size / 2) was used in both first_half and last_half.
This is what I ended up doing to get it to work. I had to change the length to a float to_f, then I could get it to test in the console correctly.
def first_half(list)
list[0...(list.length.to_f / 2).ceil]
end
def last_half(list)
list[(list.length.to_f / 2).ceil...list.length]
end
Using .ceil on both methods then allowed the math to work.

Rails - conditional display of html block

On my views I use 1 form that includes a block that renders comments. I do not want to run it when creating a new record. So, I tried conditions like so...
<% unless #annotation_id.nil? %>
<hr>
<div class="row">
<div class="col-md-8">
<h4>Comments</h4>
<%= render #annotation.comments %>
</div>
<div class="col-md-4">
<%= render 'comments/form' %>
</div>
</div>
<% end %>
This however results in never displaying the block - also when the annotation record exists. What am I doing wrong?
You don't show that you have actually set #annotation_id to something.
A simpler way might be to use the .new_record? method instead, like:
<% unless #annotation.new_record? %>
...
<% end %>
use if #annotation.persisted? or unless #annotation.new_record?

Rails: DRYing similar but different views

I have a pair of very similar views that render almost identical information, only in one view there are couple of extra columns and in the other the rows link slightly different nested resources. My initial approach was to keep it DRY by using a partial and then placing conditionals throughout the view. The resulting partial looked something like this:
<div id='overview_table'>
<div id="overview_header">
<span id="sort_title" class="title cell">Title<span id="publication_sort_arrow"> ↓</span></span>
<span id="sort_author" class="author cell">Author</span>
<span id="sort_status" class="status cell">Status</span>
<% if #user.present? %>
<span id="sort_impression_date" class="date cell">Date</span>
<span id="sort_impression_vote" class="votes cell">Votes</span>
<span id="sort_children_total" class="children_total cell">Replies</span>
<% end %>
</div>
<span id="sort_method">title ASC</span>
<% #publications.each do |publication| %>
<div class='<%= cycle("odd", "even") %>'>
<% if #user.present? %>
<% link = [#user, publication] %>
<% else %>
<% link = [#group, publication] %>
<% end %>
<%= link_to(link, :remote => true) do %>
<span class="title cell"><%= publication.full_title %></span>
<span class="author cell"><%= publication.authors %></span>
<span class="status cell"><%= publication_status(publication.status) %></span>
<% if #user.present? %>
<span class="date cell"><% if publication.impression_date %><%= publication.impression_date.strftime("%B %d, %Y") %><% end %></span>
<span class="votes cell"><% if publication.impression_vote %><%= publication.impression_vote.to_i %><% end %></span>
<span class="children_total cell"><% if publication.impression_vote %><%= publication.children_total %><% end %></span>
<% end %>
<% end %>
</div>
<% end %>
It worked fine, but the code felt hacky. I ultimately separated these back out into the two different views, though now there's a lot of repeated code. Both approaches feel inadequate. Is there another approach that I'm not considering?
There are different strategies here but in this case if you are just adding some fields, I would do something like this (which is similar to what you are doing).
in my controller I'll set some tag value to true:
#show_val_extra=true
and in my view(probably be a partial so rather than inline code in your example):
<%="something here" unless #show_val_extra.nil? %>
No matter what you are going to have to check and other issues of managing the view in the controller are ugly to me. YMMV but this is what I'd do since it basically makes it to a single value and a single check for when you want different information. Usually, it's in multiple places but you have content in multiple places and a further refactor is easy if the situation arises.

Can one use conditions and loops on a single line in Ruby?

How would one go about turning the following code into the latter?
<div id="faqs">
<% if #faqs.length > 0 %>
<% #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
<% else %>
<p>No FAQs to display.</p>
<% end %>
</div>
<div id="faqs">
<% #faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
</div>
I'm curious as to whether I can get the latter code to work. The only element of it that is failing at the moment is that the content_tag() is not displaying - this is due to the fact that I'm not using printable ruby tags (<%= # %>) but using them will dump out the FAQ objects underneath the content.
I considered the use of puts() to print the content_tag() while inside the ruby tags but that didn't work.
I've tried to search for this issue but haven't yielded anything useful.
Is this achievable and if so, does it have any benefits other than being prettier?
One way to make the later code to work if you can put the body of the loop in a helper function and return the out put of content_tag from that. The line in view file might be somewhat like this.
<%= #faqs.empty? ? content_tag(:p, "No FAQs to display.") : printList(#faqs) %>
and your printList function will return the output of nested content_tags. You can make a generic list printing function which can be used for any list.
Something so obvious but still shared.
This should work (for clarity, I moved FAQ tag generation in separate helper method):
<div id="faqs">
<%= raw (#faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.map { |faq| faq_div(faq) }.join) %>
</div>
or, perhaps more clean:
<div id="faqs">
<%= content_tag(:p, "No FAQs to display.") if #faqs.empty? %>
<%= raw #faqs.map { |faq| faq_div(faq) }.join %>
</div>
meanwhile, in helpers:
def faq_div(faq)
'<div class="faq"><strong>Q:</strong> %s<br /><strong>A:</strong> %s</div>' % [faq.question, faq.answer]
end
This should work:
<% if #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end.empty? %>
<p>No FAQs to display.</p>
<% end %>

Resources