Conditional tag wrapping in Rails / ERB - ruby-on-rails

What would be the most readable and/or concise way to write this in ERB? Writing my own method isn't preferable, as I would like to spread a cleaner solution for this to others in my company.
<% #items.each do |item| %>
<% if item.isolated? %>
<div class="isolated">
<% end %>
<%= item.name.pluralize %> <%# you can't win with indentation %>
<% if item.isolated? %>
</div>
<% end %>
<% end %>
== Update ==
I used a more generic version of Gal's answer that is tag agnostic.
def conditional_wrapper(condition=true, options={}, &block)
options[:tag] ||= :div
if condition == true
concat content_tag(options[:tag], capture(&block), options.delete_if{|k,v| k == :tag})
else
concat capture(&block)
end
end
== Usage
<% #items.each do |item| %>
<% conditional_wrapper(item.isolated?, :class => "isolated") do %>
<%= item.name.pluralize %>
<% end %>
<% end %>

If you really want the DIV to be conditional, you could do something like this:
put this in application_helper.rb
def conditional_div(options={}, &block)
if options.delete(:show_div)
concat content_tag(:div, capture(&block), options)
else
concat capture(&block)
end
end
which then you can use like this in your view:
<% #items.each do |item| %>
<% conditional_div(:show_div => item.isolated?, :class => 'isolated') do %>
<%= item.name.pluralize %>
<% end %>
<% end %>

Try:
<% #items.each do |item| %>
<div class="<%= item.isolated? 'isolated' : '' %>">
<%= item.name.pluralize %>
</div>
<% end %>

I like PreciousBodilyFluids' answer, but it doesn't strictly do exactly what your existing method does. If you really cannot have a wrapping div, this may be prefereable:
<% #items.each do |item| %>
<% if item.isolated? %>
<div class="isolated">
<%= item.name.pluralize %>
</div>
<% else %>
<%= item.name.pluralize %>
<% end %>
<% end %>
A helper method to do all of this would probably look like this:
def pluralized_name_for(item)
if item.isolated?
content_tag(:div, item.name.pluralize, :class => 'isolated')
else
item.name.pluralize
end
end
Then your view code would look like this:
<% #items.each do |item| %>
<%= pluralized_name_for(item) %>
<% end %>

Related

Rails loop in html erb

How can I simplify the following lines:
<% if #campaign.previous_campaign.present? %>
<%= #campaign.previous_campaign.product_name %>
<% if #campaign.previous_campaign.previous_campaign.present? %>
<%= #campaign.previous_campaign.previous_campaign.product_name %>
<% end %>
<% end %>
I need to keep adding ".previous_campaign" until it is not present. So the next one in the above code would be:
<%= #campaign.previous_campaign.previous_campaign.previous_campaign.product_name %>
etc etc.
Something like this:
<% campaign = #campaign %>
<% while campaign.previous_campaign.present? %>
<% campaign = campaign.previous_campaign %>
<%= campaign.product_name %>
<% end %>
The code may need some debugging, but I guess the idea is clear
You could do something like this:
<% for c in #campaign do %>
<% if c.previous_campaign.present? %>
<%= c.previous_campaign.product_name %>
<% end %>
<% end %>

How can I make this sophistictaed?

I'm trying to change this pagination to reverse pagination. from
|Last|Next|25|24|23|22|21|Previous|First|
to
|First|Previous|21|22|23|24|25|Next|Last|
So, I coded like this below, but it takes so long. It's probably because it fetches all the comments in order to pass argument first, and then it does again in application_controller.rb
Is there any smart way to make this faster?
user_controller.rb
#comments = reverse_paginate(Comment.where(:user_id => user_ids, :commentable_type => commentable).order('created_at DESC'), params[:page])
application_controller.rb
def reverse_paginate(scope, page)
if page
page_number = page
else
page_number = Kaminari.paginate_array(scope.reverse).page(1).per(10).num_pages
end
Kaminari.paginate_array(scope.reverse).page(page_number).per(10).reverse!
end
I think you'll have to override the paginator template of Kaminari.
<%= paginator.render do -%>
<nav class="pagination">
<%= first_page_tag unless current_page.first? %>
<%= prev_page_tag unless current_page.first? %>
<% each_page do |page| -%>
<% if page.left_outer? || page.right_outer? || page.inside_window? -%>
<%= page_tag page %>
<% elsif !page.was_truncated? -%>
<%= gap_tag %>
<% end -%>
<% end -%>
<%= next_page_tag unless current_page.last? %>
<%= last_page_tag unless current_page.last? %>
</nav>
<% end -%>
Source here

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

TypeError: can't convert Symbol into Integer

I get a "TypeError in Activities#member - can't convert Symbol into Integer"
I would say that 95% of my records work fine but I have a couple that keep tripping this error. Where do I start to look at this problem.
Here is the code I am working with:
.html.erb page
<div id="listing-gallery">
<ul id="listing-slides">
<% listing.slides.each_with_index do |slide, i| %>
<%= content_tag :li, :id => "slide#{i}", :class => (i == 0) ? "active" : "" do %>
<%= image_tag slide[:large] %>
<% end %>
<% end %>
</ul>
<ul id="listing-slide-thumbs">
<% if listing.slides.count > 1 %>
<% listing.slides.each_with_index do |slide, i| %>
<%= content_tag :li, :class => (((i+1)%4 == 0) ? "last" : "") do %>
<%= content_tag :a, :href => "#slide#{i}" do %>
<span class="hover"></span>
<%= image_tag slide[:thumb] %>
<% end %>
<% end %>
<% end %>
<% end %>
</ul>
.activities_controller.rb
def member
# Assign attrs if venue exists
if #member.nil? || #member.venue.nil?
redirect_to activities_path
else
if #member.venue.attrs.count > 0
# match_by_type can be found in the ApplicationHelper
#attrs = match_by_type #member.venue.attrs
else
#attrs = nil
end
unless #member.venue.nil?
unless #member.venue.attrs.nil?
#member_rentals = #member.venue.attrs.all_by_type("Rentals")
end
end
end
end
Where do I go from here?
see <%= image_tag slide[:large] %> and <%= image_tag slide[:thumb] %>
what image attribute for slide?
If image is attribute for slide, I think such as :
<%= image_tag slide.image.url(:large) %>
or if usinng carrierwave
<%= image_tag slide.image_url(:large).to_s %>
By the way, I don't see listing.slides on action member

Using to_sentence

I'm a newbie...
I know how to use "to_sentence" when I have something like:
<%= #blah.collect {|b| b.name}.to_sentence %>
but what if I have a more complex block like:
<% skill.position.each do |position| %>
<%= position.company.name %>
<% if position.salary? %>
<span><%= position.salary %></span>
<% end %>
<% end %>
The desired output is:
Microsoft, Google 2000, and Yahoo.
Couldn't you just collect it without .each?
<%= skill.positions.collect{ |p| "#{p.company.name}#{position.salary? ? '<span>#{position.salary}</span>' : nil}" }.to_sentence %>
That should work for you...
You could also do this:
<%= skill.position.each do |position| %>
<% position.company.name %>
<% if position.salary? %>
<span><% position.salary %></span>
<% end %>
<% end.to_sentence %>
The to_sentence methods works on Arrays. The reason that it works on your first example...
<%= #blah.collect {|b| b.name}.to_sentence %>
... is because the collect method returns an Array. The each method in your second example will also work because each also returns an Array. So, this will work:
<% blah.each do |b| %>
...
<% end.to_sentence %>

Resources