Rails Odd Even If Statement - ruby-on-rails

I have a loop for my Activity model
<% #activities.each do |activity| %>
<div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
</div>
<% end %>
I want to create a zig-zag effect, so I need to re-arrange the HTML for every even activity, so the markup will look like this:
<div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
</div>
Is there a way to do this with an if statement? Something like this:
<% if activity.odd? %>
<% #activities.each do |activity| %>
<div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
</div>
<% end %>
<% else %>
<% #activities.each do |activity| %>
<div>
<div class="cell">
<h4><%= activity.title %></h4>
<p><%= activity.description %></p>
<span><%= activity.distance %></span>
</div>
<div class="cell">
<%= image_tag(activity.image) %>
</div>
</div>
<% end %>

There are a few ways to do this.
The first and best way is to do this with CSS's nth-child selector, assuming it's possible to achieve your desired effect purely through CSS. Use nth-child(odd) or nth-child(even), as described in Alternate table row color using CSS?
If you're iterating over a collection using .each, you can add a .with_index and check whether the index is odd or even:
<% #activities.each.with_index do |activity, index| %>
<% if index.odd? %>
...
<% else %>
...
<% end %>
<% end %>
Note that by default the index is zero-based, so your first element will be considered "even". You can pass a starting index of 1 to with_index if you want the alternating to start odd instead:
<% #activities.each.with_index(1) do |activity, index| %>
An alternative to using with_index is to use Rails' cycle helper, which "magically" returns the next argument in rotation each time its invoked:
<% #activities.each do |activity| %>
<% if cycle('odd', 'even') == 'odd' %>
...
<% end %>
<% end %>
Also note that this is a fantastic opportunity for refactoring. You should distill the two reused cell divs into their own partials and render them in the order you want:
<% if index.odd? %>
<%= render h4_part %>
<%= render img_part %>
<% else %>
<% render img_part %>
<% render h4_part %>
<% end %>

Related

Trouble sorting my erb view into groups with in_groups_of

I am trying to use in_groups_of to sort my rails html output into two columns. Right now it just displays as one column. Here is the code:
<% #providers.in_groups_of(2).each do |group| %>
<div class="row">
<% group.each do |provider| %>
<div class="col-xs-6">
<h3><%= link_to provider.name, provider_path(provider) %></h3>
<h4><%= provider.address %></h4>
</div>
<% end %>
Your div.col-md-12s are each taking up the width of an entire row. Try changing them to col-xs-6. (I'm using xs so it will show up on any size of window; ignore this if not appropriate to your situation.)
<% #provider.in_groups_of(2).each do |group| %>
<div class="row">
<% group.each do |provider| %>
<div class="col-xs-6">
<h3><%= link_to provider.name, provider_path(provider) %></h3>
<h4><%= provider.address %></h4>
</div>
<% end %>
</div>
<% end %>

Dynamically generate all products on a responsive view using Bootstrap's Grid system

I want to generate all my products and their information on a page using bootstrap's grid system. I tried to generate three products in a row at first and it worked using the following code:
<div class="container">
<h1 align="center">Listing products</h1>
<% #products.each do |product| %>
<% if #a%3 == 0 %>
<div class="row">
<% end %>
<div class="col-lg-4">
<%= image_tag(product.image_url, class: 'list_image', size: '260x320') %>
<%= product.title %> <br/>
<%= product.price %> <br/>
<%= link_to 'Show', product %><br/>
</div>
<% #a = #a+1 %>
<% if #a%3 == 0 %>
</div><hr/>
<% end %>
<% end %>
</div>
(#a is what I declared in the controller which is initially set to 0)
The code will not work anymore if I want to only display two or less products in a row using the grid system when the screen gets smaller.
Are there any better ideas to achieve this?
Seems like you are generating incorrect HTML markup. Try to use each_slice:
<div class="container">
<h1 align="center">Listing products</h1>
<% #products.each_slice(3) do |products| %>
<div class="row">
<% products.each do |product| %>
<div class="col-lg-4">
<%= image_tag(product.image_url, class: 'list_image', size: '260x320') %>
<%= product.title %> <br/>
<%= product.price %> <br/>
<%= link_to 'Show', product %><br/>
</div>
<% end %>
</div>
<hr/>
<% end %>
</div>

Conditional link_to block in Rails if condition is met

I would like to wrap a conditional link_to around some code that only renders the link if the following condition is met: IF current_user.type == 'Agent'. The content within the condition still needs to be rendered regardless.
My current block looks like this:
<% #jobs_published.in_groups_of(3, false) do |job| %>
<div class="row">
<%= link_to "/job/#{job.id}" do %>
<div class="panel">
<h4>Job</h4>
<p><%= job.suburb %></p>
<p><%= job.street_name %></p>
<p><%= job.post_cide %></p>
</div>
<% end %>
</div>
<% end %>
I solved this by doing the following:
View:
<% #jobs_published.in_groups_of(3, false) do |job| %>
<div class="row">
<%= link_to_if current_user && current_user.type == 'Agent', { controller: "agents", action: "job", :id => job.id } do %>
<div class="panel">
<h4>Job</h4>
<p><%= job.suburb %></p>
<p><%= job.street_name %></p>
<p><%= job.post_cide %></p>
</div>
<% end %>
</div>
<% end %>
ApplicationHelper:
def link_to_if(*args,&block)
args.insert 1, capture(&block) if block_given?
super *args
end
Reference: https://stackoverflow.com/a/25916594/2811283
You can try the below one
<% #jobs_published.in_groups_of(3, false) do |job| %>
<div class="row">
<%= link_to_if(current_user.type == 'Agent', "/job/#{job.id}") do %>
<div class="panel">
<h4>Job</h4>
<p><%= job.suburb %></p>
<p><%= job.street_name %></p>
<p><%= job.post_cide %></p>
</div>
<% end %>
</div>
<% end %>
There are many conditional link_to element
link_to_if , link_to_unless, link_to_unless_current
You should use link_to_if.
Here is the documentation link. http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to_if

Appending a icon based on the project count

I have a row which displays projects, now i need to add an icon to the end if the number of items exceed 6. How can write a condition here to check if the project count is greater than 6 then instead of adding the projects i append a icon.
<div class="row">
<% #projects.each do |project| %>
<div class="col-sm-2 col-xs-1">
<%= link_to project.name, project_url(project.project_id),
class: ('active' if current_page?(project_path(project.project_id)) ) %>
</div>
<% end %>
</div>
You could try using each_with_index and then have a conditional in the loop to detect when you're on the 6th loop (first loop begins with zero for the index value).
Something like this:
<div class="row">
<% #projects.each_with_index do |project, index| %>
<% if index > 5 >
<!-- show icon -->
<% else %>
<div class="col-sm-2 col-xs-1">
<%= link_to project.name, project_url(project.project_id),
class: ('active' if current_page?(project_path(project.project_id)) ) %>
</div>
<% end %>
<% end %>
</div>
I think this is what you want. If not then feel free to ask for change.
<% if #projects.size > 6 %>
###put your icon here
<% else %>
<div class="row">
<% #projects.each do |project| %>
<div class="col-sm-2 col-xs-1">
<%= link_to project.name, project_url(project.project_id),
class: ('active' if current_page?(project_path(project.project_id)) ) %>
</div>
<% end %>
</div>
<% end %>
You can use 'each_with_index' instead of each , like this
<%#images.each_with_index do |page, index| %>
<% if index > 5 %>
//here put your code to add icon
<%else%>
<%= link_to project.name, project_url(project.project_id),
class: ('active' if current_page?(project_path(project.project_id))
<%end%>
<%end%>
I think it will help you

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 %>

Resources