link_to in ruby on rails with additional html - ruby-on-rails

I know there are more of these, but I couldn't find my answer as I'm still fairly new to RoR.
I need to take this:
<% if params[:forum_id] %>
<%= link_to "#{category.name}", category_path(category.id,:forum_id => params[:forum_id]) %>
<% else %>
<%= link_to "#{category.name}", category_path(category.id) %>
<% end %>
which prints out:
name
and I need:
<a href="mylink....">
<figure></figure>
<span>name</span>
</a>
Thanks!

You can use link_to as a block:
<%= link_to category_path(category_id) do %>
<figure></figure>
<span><%= category.name %></span>
<% end %>
EDIT
The full solution:
<% if params[:forum_id] %>
<%= link_to category_path(category.id,:forum_id => params[:forum_id]) do %>
<figure></figure>
<span><%= category.name %></span>
<% end %>
<% else %>
<%= link_to category_path(category.id) do %>
<figure></figure>
<span><%= category.name %></span>
<% end %>
<% end %>

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 improve code in Views on Ruby on Rails

I have code in file views name: _result.html.erb, this file is rendered from file show.html.erb, both file in one folder
File _result.html.erb
<% if #lesson.answers.at(f.index).is_correct %>
<% if #lesson.answers.at(f.index).id == answer.id %>
<li class="text-success">
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
<% else %>
<li>
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
<% end %>
<% else %>
<% if #lesson.answers.at(f.index).id == answer.id %>
<li class="text-danger">
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
<% else %>
<li>
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
<% end %>
<% end %>
And I want to improve this code in file _result.html.erb for shorter, help me please!!!
File show.html
<% provide :title, t("start_lesson") %>
<h1><%= #course.name %></h1>
<h2><%= #course.description %></h2>
<h3><%= t "title_question" %></h3>
<% if #lesson.finished.present? %>
<h4>
<%= t "score" %>:
<%= #lesson.results.is_correct_answers.count %> /
<%= #lesson.words.count %>
</h4>
<% end %>
<%= form_for [#course, #lesson] do |f| %>
<%= f.fields_for :results do |builder| %>
<ul class="list-unstyled">
<li>
<%= "#{builder.index + 1}." %>
<%= #words.at(builder.index).content %>
</li>
<ul class="list-unstyled">
<% #words.at(builder.index).answers.each do |answer| %>
<% if #lesson.finished.nil? %>
<li>
<%= answer.content %>
<%= builder.radio_button :answer_id, answer.id %>
<%= builder.hidden_field :word_id, value: answer.word.id %>
</li>
<% else %>
<%= render "result", f: builder, answer: answer %>
<% end %>
<% end %>
</ul>
</ul>
<% end %>
<% if #lesson.finished.nil? %>
<%= f.submit t("submit"), class: "btn btn-primary" %>
<% end %>
<% end %>
This is just a code-rewrite exercise, so here goes:
result.html.erb
<% if #lesson.answers.at(f.index).id == answer.id %>
<% if #lesson.answers.at(f.index).is_correct %>
<li class="text-success">
<% else %>
<li class="text-danger">
<% end %>
<% else %>
<li>
<% end %>
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
or the shorter (but much harder to read) version:
<li<% if #lesson.answers.at(f.index).id == answer.id %>class="<%= #lesson.answers.at(f.index).is_correct ? "text-success" : "text-danger" %>" <% end%>>
<%= f.radio_button :answer_id, answer.id, disabled: true %>
<%= answer.content %>
</li>
In the first example, the condition was inverted to take advantage of the fact that the else condition in both interior conditions was identical, and then using the conditions only to style the <li> node, since that was the only difference between the 4 blocks.
The second example goes further and does the conditional checks inline with the element, building the class attribute when necessary. This is much harder to read at a glance, but is far more compact.
show.html
<% provide :title, t("start_lesson") %>
<h1><%= #course.name %></h1>
<h2><%= #course.description %></h2>
<h3><%= t "title_question" %></h3>
<% if #lesson.finished.present? %>
<h4><%= "#{t 'score'}: #{#lesson.results.is_correct_answers.count} / #{#lesson.words.count} %></h4>
<% end %>
<%= form_for [#course, #lesson] do |f| %>
<%= f.fields_for :results do |builder| %>
<ul class="list-unstyled">
<li><%= "#{builder.index + 1}.#{#words.at(builder.index).content}" %></li>
<ul class="list-unstyled">
<% #words.at(builder.index).answers.each do |answer| %>
<% if #lesson.finished.nil? %>
<li>
<%= answer.content %>
<%= builder.radio_button :answer_id, answer.id %>
<%= builder.hidden_field :word_id, value: answer.word.id %>
</li>
<% else %>
<%= render "result", f: builder, answer: answer %>
<% end %>
<% end %>
</ul>
</ul>
<% end %>
<% if #lesson.finished.nil? %>
<%= f.submit t("submit"), class: "btn btn-primary" %>
<% end %>
<% end %>
Most of the changes here are just using string interpolation to combine string elements that are otherwise multiple <%= %> blocks.
The larger loop portion that builds the list of answers has some possible issues. For instance, the rendered result (when the lesson is not finished) is missing the <li> and </li> elements, so the answers are simply sitting as a blob of text within the enclosing <ul>. In order to preserve that, in case it was intentional, most of the middle block remained.
However, this is probably not what you actually wanted, so this version fixes that and does a little more reorganization:
<% provide :title, t("start_lesson") %>
<h1><%= #course.name %></h1>
<h2><%= #course.description %></h2>
<h3><%= t "title_question" %></h3>
<% if #lesson.finished.present? %>
<h4><%= "#{t 'score'}: #{#lesson.results.is_correct_answers.count} / #{#lesson.words.count} %></h4>
<% end %>
<%= form_for [#course, #lesson] do |f| %>
<%= f.fields_for :results do |builder| %>
<ul class="list-unstyled">
<li><%= "#{builder.index + 1}.#{#words.at(builder.index).content}" %></li>
<ul class="list-unstyled">
<% #words.at(builder.index).answers.each do |answer| %>
<li>
<% if #lesson.finished.nil? %>
<%= answer.content %>
<%= builder.radio_button :answer_id, answer.id %>
<%= builder.hidden_field :word_id, value: answer.word.id %>
<% else %>
<%= render "result", f: builder, answer: answer %>
<% end %>
</li>
<% end %>
</ul>
</ul>
<% end %>
<% if #lesson.finished.nil? %>
<%= f.submit t("submit"), class: "btn btn-primary" %>
<% end %>
<% end %>
That's about the shortest this can be without collapsing the structure or just removing whitespace. Each remaining element seems to have a purpose and is placed where it should be, without redundancy or over-complication.

Rendering a partial inside a block

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'.

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

Whats wrong with this else if statement?

Basically my controller is just grabbing all members: #members = Member.all and Im looping through them while checking to see if they have a profile picture uploaded and if not then the default should be loaded:
<% #members.each do |member| %>
<% unless member.image.nil? %>
<li style="float:left; width:100px;">
<%= image_tag(member.image.url(:tiny)) %>
<%= link_to member.email, member_path(member) %>
</li>
<% else %>
<li style="float:left; width:100px;">
<%= image_tag("default_member_small.jpg") %>
<%= link_to member.email, member_path(member) %>
</li>
<% end %>
<% end %>
It seems to think every member has a profile image, and the image tag is calling "images/tiny/missing.png" for the missing images.
What gives?
I am guessing you are using paperclip, if you are, you should not use nil?, you should use present?:
<% #members.each do |member| %>
<% if member.image.present? %>
<li style="float:left; width:100px;">
<%= image_tag(member.image.url(:tiny)) %>
<%= link_to member.email, member_path(member) %>
</li>
<% else %>
<li style="float:left; width:100px;">
<%= image_tag("default_member_small.jpg") %>
<%= link_to member.email, member_path(member) %>
</li>
<% end %>
<% end %>
And instead of having an if you should just have this image named as paperclip expects it, there should not have any ifs in your code for this kind of handling.

Resources