Rendering a partial inside a block - ruby-on-rails

I'm new to rails. I have this block in my view afrikaans.html.erb
<% #afrikaans.each do |course| %>
<div class="course">
<h3 class="course-name"><%= link_to course.name, course.url %></h3>
<% if I18n.locale == I18n.default_locale %>
<p class="course-description_en"><%= course.description_en %></p>
<% else %>
<p class="course-description_se"><%= course.description_se %></p>
<% end %>
<% if course.youtube_url.blank? == false %>
<p><%= raw ApplicationHelper.youtube_embed(course.youtube_url) %></p>
<% end %>
<% if course.language_id == 1 %>
<p> <%= image_tag("eng.png", :alt => "England", :class =>"round") %></p>
<% else %>
<p> <%= image_tag("swe.png", :alt => "Sweden", :class =>"round") %></p>
<% end %>
<% if ApplicationHelper.active_link?(course.url) == false %>
<td><%= I18n.t('home.broken_link') %></td>
<% end %>
<p><%= course.nbr_of_votes %> <%= I18n.t('home.votes') %></p>
</tr>
<% end %>
I also have another file swahili.html.erb with the same structure. I wanted to implement something like this
afrikaans.html.erb
<% #afrikaans.each do |course| %>
<%= render 'shared/partial' %>
<% end %>
So that I can also have
swahili.html.erb
<% #swahili.each do |course| %>
<%= render 'shared/partial' %>
<% end %>
The partial will contain the part of the block. I've tried this but it's not working. My question is this even possible in rails and if so what could be the problem. What options do I have if it isn't possible so that I can avoid the repetition since the two files have the same structure?
Update. This One worked out for me. I only needed to add :course => course on the block so that my views becomes something like
<% #afrikaans.each do |course| %>
<%= render 'shared/course_body', :course => course %>
<% end %>
Of course I've not named my partial "partial". This was just a matter of asking. Thanks to one #Alexander Panasyuk's answer.

Just create shared directory within your app/views path. And create file _partial.html.erb inside shared:
<div class="course">
<h3 class="course-name"><%= link_to course.name, course.url %></h3>
<% if I18n.locale == I18n.default_locale %>
<p class="course-description_en"><%= course.description_en %></p>
<% else %>
<p class="course-description_se"><%= course.description_se %></p>
<% end %>
<% if course.youtube_url.blank? == false %>
<p><%= raw ApplicationHelper.youtube_embed(course.youtube_url) %></p>
<% end %>
<% if course.language_id == 1 %>
<p> <%= image_tag("eng.png", :alt => "England", :class =>"round") %></p>
<% else %>
<p> <%= image_tag("swe.png", :alt => "Sweden", :class =>"round") %></p>
<% end %>
<% if ApplicationHelper.active_link?(course.url) == false %>
<td><%= I18n.t('home.broken_link') %></td>
<% end %>
<p><%= course.nbr_of_votes %> <%= I18n.t('home.votes') %></p>
</tr>
Then render your partial in afrikaans.html.erb like that:
<% #afrikaans.each do |course| %>
<%= render 'shared/partial', :course => course %>
<% end %>
or in swahili.html.erb:
<% #swahili.each do |course| %>
<%= render 'shared/partial', :course => course %>
<% end %>

It is most definitely possible, and usually a good idea.
In the future it would be nice if you could post the actual results and/or error messages you get, which would help a lot when trying to help you.
That said, I'm guessing you need to pass the course variable to your partial. Change
<%= render 'shared/partial' %>
to
<%= render 'shared/partial', :course => course %>
Partials do not have access to local variables in other partials. In that sense you can think of each partial as separate methods on the same object instance.

<%= render 'shared/partial', locale: 'swahili', course: course %>
You will have local vars 'locale' and 'course' in your partial set to 'swahili' and #course, respectively. Also, I'd advise to name your partials something more meaningful, like 'course'.

Related

Rails: how to create a list with conditional links

I am working on a RAILS application where I create a view which lists all available resources of a given model species.rb.
The view partial is:
<% i= #s
for species in #species %>
<%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %>
<% i -= 1
end %>
Some of the resources species have an related article, others have only the name. I would like to loop through the partial and add a link only to the entries which have an associated article.
Something like: add link if species.article is present else just put species.name without link + loop through it for all entries.
How can I do this?
UPDATE:
Thanks to #jvillian and #fool-dev I was able to progress. In my case I wanted to add a link if the resource has a description in a description row of its table.
<% #species.each do |species| %>
<div class="entry">
<p><i><%= link_to_if(species.txtlandscape.present?, "#{species.name}, #{species.author.surname}, #{species.author.initial_name}. 2014", :controller => 'projects', :action => 'show', :id => species) %></i></p>
</div>
<% end %>
Now that a link is added I was wondering if it can be used to load a partial to a target such as in, where ArticleRequest is a JS function I have:
<% # species.each do | species | %>
<div id="species-<%= species.id %>" class="species-entry">
<a onClick="ArticleRequest('/species/show/<%= species.id %>', 'species-<%= species.id %>');">
<p><%= species.name %></p>
</a>
</div>
<% end %>
Until I find a way to do this with link_to_if, I will use something like:
<% for species in #species %>
<% if species.txtlandscape.present? %>
<a onClick="ArticleRequest('/species/show/<%= species.id %>', 'species-<%= species.id %>');">
<p><%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %></p>
</a>
<% else %>
<p><%= species.name %>, <%= species.author.surname %> <%= species.author.initial_name %></p>
<% end %>
<% end %>
According to the docs, it seems you should be able to do:
<% #species.each do |specie| %>
<%= link_to_if(specie.article, specie.name, specie_article_path(specie.article)) %>
<% end %>
I made the path name up, you'll have to make that match your actual routes.
BTW, this:
for species in #species
Is super non-idiomatic.
You can do this, see the below
<% for species in #species %>
<% if species.article.present? %> #=> I thin it will be articles because table name is articles, anyway, you know better
<%= link_to species.name, link_path(species.article) %>, #=> on the link_path it will be your proper link just replace this
<% else %>
<%= species.name %>,
<% end %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
You can do this with Rails each method like below
<% #species.each do |species| %>
<% if species.article.present? %> #=> I thin it will be articles because table name is articles, anyway, you know better
<%= link_to species.name, link_path(species.article) %>, #=> on the link_path it will be your proper link just replace this
<% else %>
<%= species.name %>,
<% end %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
Or you can use link_to_if it is also most easier to understand
<% #species.each do |species| %>
<%= link_to_if(species.article.present?, "#{species.name},", link_path(species.article)) %>
<%= species.author.surname %> <%= species.author.initial_name %>
<% end %>
Hope it will help.

How to display related items

I want to display related experiences below the local experiences. I tried to do it using #experiences= Experience.excludes(house.experiences) but didnt work out. Can I get any suggestion how to do that.
<h3>Local experiences</h3>
<section class="list-box">
<% #house.experiences.each do |experience| %>
<p>
<%= experience.name %>
<% if logged_in? && current_user.role == "customer" %>
<%= link_to "Make Enquiry", new_message_path(receiver_id: experience.supplier.user) %>
<% else %>
<%= link_to "Make Enquiry", new_customer_path %>
<% end %>
</p>
<% end %>
</section>
<h3>Related experiences</h3>
<section class="list-box">
<% #experiences.each do |experience| %>
<p>
<%= experience.name %>
<% if logged_in? && current_user.role == "customer" %>
<%= link_to "Make Enquiry", new_message_path(receiver_id: experience.supplier.user) %>
<% else %>
<%= link_to "Make Enquiry", new_customer_path %>
<% end %>
</p>
<% end %>
</section>
There is no method called excludes in the rails model. There is only exclude?, which is a instance method of class String. Refer here.
For your issue, maybe something like below would work given that house_id is the foreign_key in your experience table.
#experiences = Experience.where.not(house_id: house.experiences)
You may refer here for more not conditions.

Unable to get the value of a variable inside Rails erb tags

I want to understand the erb usage. In the below code I am unable to figure out how to get the value of (group.id) in the if clause using the erb tags.
This probably has a very basic solution but I am unable to get proper answers.
The below code gives me syntax error.
<% current_user.favorite_groups.to_a.each do |group| %>
<%= if (group.id).newfavorite_texts.exists?(id: text.id) %>
<%= group.name %>
<%= link_to # do something %>
<% else %>
<%= group.name %>
<%= link_to # do something else %>
<% end %>
<% end %>
Thanks in advance.
You should be get going with the below code
<% current_user.favorite_groups.to_a.each do |group| %>
<% if group.newfavorite_texts.exists?(id: text.id) %>
<%= group.name %>
<%= link_to # do something %>
<% else %>
<%= group.name %>
<%= link_to # do something else %>
<% end %>
<% 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 %>

Only show non blank attributes for a model in views in Rails

Say I've a user model and there are bunch of user info, like email, birthdate, location, telephone number etc.
What's the simplest way of hiding the attributes that are blank?
I've doing something like
<% if blog.title.empty? -%>
<p>Body: <%=h blog.body %></p>
<p>Comments: <%=h blog.comments %></p>
<% elsif blog.body.empty? %>
<p>Title: <%=h blog.title %></p>
<p>Comments: <%=h blog.comments %></p>
<% else -%>
<p>Title: <%=h blog.title %></p>
<p>Body: <%=h blog.body %></p>
<% end -%>
Clearly that is one ugly child. Other than using partials to render, is there a trick to only show non blank fields?
I've been trying to write a helpher method to make the view cleaner, but that's even more ugly.
Any help is appreciated.
I would do it like this:
# blog_helper.rb
show_non_blank_field(label, value)
"<p>#{label}: #{h value}</p>" if !value.blank?
end
and then in view:
<%= show_non_blank_field "Body", blog.body %>
and so on...
Of course you can use shorter helper name.
If you want to do it in if-else way, try this:
<% if !blog.title.blank? -%>
<p>Title: <%=h blog.title %></p>
<% end %>
<% if !blog.body.blank? %>
<p>Body: <%=h blog.body %></p>
<% end %>
<p>Comments: <%=h blog.comments %></p>
show_field_unless_empty(blog, :body, 'Body')
then, in blog_helper.rb
def show_field_unless_empty(model, field, title)
render :partial => 'field', :locals => {:value => model.send(field), :title => title} if model.send(field)
end
then, in _field.html.erb
<p>
<%= title %>:
<%= value %>
</p>
This seems fairly clean to me.

Resources