How to concatenate items from loop [duplicate] - ruby-on-rails

This question already has an answer here:
Rails separate array items with comma inside partial
(1 answer)
Closed 8 years ago.
I wonder if there's a quick way to concatenate the items from this view helper with a comma:
<% #projects.each do |project| %>
<%= link_to project.name, project_path(project) %>
<% end %>
so that I get:
Project name 1, Project name 2, Project name 3
Note that there's no comma at the end. Thanks for any ideas.

What about
<%= #projects.map { |p| link_to p.name, project_path(p) }.join(', ').html_safe %>
I added sanitize to p.name because otherwise if some special character is present in p.name it would break your HTML (and could lead to security issues, that is XSS attacks) I was wrong, I tried and it is escaped correctly.

<%= #projects.map {|project| link_to project.name, project_path(project)}.join(", ").html_safe %>

Related

Use of <%= %> instead of <% %> ruby on rails [duplicate]

This question already has an answer here:
embedded ruby syntax "<%= .. %>" in rails [duplicate]
(1 answer)
Closed 8 years ago.
I've been following Agile Web Development with Rails, and their code suddenly switches from the use of <%= %> to <% %>.
Code Example 1:
<%= 1+2 %>
Code Example 2:
<% for file in #files %>
file name is: <%= file %>
<% end %>
My question is, for the second code sample why can I not use <%= %>?
Thanks!
In ERB (embedded ruby) syntax, <%= %> is shorthand for "perform the following ruby code AND THEN print the result". So in the first example, it will print the result of the operation 1 + 2, 3.
The second example shows a for loop which will iterate and print the contents between the for declaration and its corresponding <% end %>.
To answer your question, the expression for file in #files itself doesn't return anything worth printing so there's no need to use <%= %> and in fact doing so can cause a hard-to-track-down bug.

Rails instance variable join

This is so simple but it's been ages since I needed this.
I have the following code
<% #miniature.minisets.each do |miniset| %>
<%= link_to miniset.name, miniset %>
<% end %>
It outputs Minisetname Minisetname Minisetname etc
I want it to output Minisetname, Minisetname, Minisetname with commas.
I've tried to include .join(", ") but can't find the right place to put it. Do I also need to use .map instead of .each?
Ignominy.
Here's one way that ought to work:
<%= #miniature.minisets.map { |miniset| link_to miniset.name, miniset }.join(", ").html_safe %>

Why many people use "-%>" instead of "%>" in Rails? [duplicate]

This question already has answers here:
What is the difference between <%, <%=, <%# and -%> in ERB in Rails?
(7 answers)
Closed 8 years ago.
Sorry for this question, i think its more offtopic, but i couldn't find anything on google!
I saw now multiple times that a lot of people use -%> instead of just %>. Whats the sense?
Example:
<% #images.each_slice(6) do |slice| -%>
<div class="gallery">
<% slice.each do |image| -%>
<%= image_tag(image.url, :alt => image.alt) %>
<% end -%>
</div>
<% end -%>
Source: Rails each loop insert tag every 6 items?
Here he has also used -%> for all blocks.
I would like to add some resources that I know about ERB :
Rails extends ERB, so that you can suppress the newline simply by adding a trailing hyphen to tags in Rails templates:
<ul>
<% for #item in #items -%>
<li><%= #item %></li>
<% end -%>
</ul>
Comment markers use a hash sign:
<%# This is just a comment %>
A tag with an equals sign indicates that enclosed code is an expression, and that the renderer should substitute the code element with the result of the code (as a string) when it renders the template. Use an expression to embed a line of code into the template, or to display the contents of a variable:
Hello, <%= #name %>.
Today is <%= Time.now.strftime('%A') %>.
With one equal sign the string will be encoded. To avoid encoding, you can use two equals signs (or raw):
Hello, <%== #unencodedOutput %>
Tags without the equals sign denote that the enclosed code is a scriptlet. Each scriptlet is caught and executed, and the final result of the code is then injected in to the output at the point of the scriptlet.
<ul>
<% for #item in #shopping_list %>
<li><%= #item %></li>
<% end %>
</ul>
Scriptlets are most commonly used for embedding loops or conditional logic into templates:
Read An Introduction to ERB Templating to know more.

Printing elements of array using ERB [duplicate]

This question already has answers here:
What is the difference between <%, <%=, <%# and -%> in ERB in Rails?
(7 answers)
Closed 3 years ago.
I'm trying to print a simple array defined in my controller into my view with a new line for each element. But what it's doing is printing the whole array on one line.
Here's my controller:
class TodosController < ApplicationController
def index
#todo_array = [ "Buy Milk", "Buy Soap", "Pay bill", "Draw Money" ]
end
end
Here's my view:
<%= #todo_array.each do |t| %>
<%= puts t %><\br>
<% end %>
Here's the result:
<\br> <\br> <\br> <\br> ["Buy Milk", "Buy Soap", "Pay bill", "Draw Money"]
Erb, the templating engine you're using in your views, has a few different ways of embedding ruby code inside templates.
When you put code inside <%= %> blocks, erb evaluates the code inside and prints the value of the last statement in the HTML. Since .each in ruby returns the collection you iterated over, the loop using <%= %> attempts to print a string representation of the entire array.
When you put code inside <% %> blocks, erb just evaluates the code, not printing anything. This allows you to do conditional statements, loops, or modify variables in the view.
You can also remove the puts from puts t. Erb knows to try to convert the last value it saw inside <%= %> into a string for display.
Hey why are you putting '=' sign in first line. <% %> are used for telling rails that string under this is ruby code,evaluate it. Where as <%= %> this tells rails that string in these tags is in ruby, evaluate it and print the result in html file too.
Hence try to inspect your code you are writing
<%= #todo_array.each do |t| %>
while this line is only for iterating over #todo_array hence we wont be in need to print that line. So final code should be
<% #todo_array.each do |t| %>
<%= puts t %>
<% end %>
Just try:
<%= #todo_array.join('<br />').html_safe %>
instead of
<%= #todo_array.each do |t| %>
<%= puts t %><\br>
<% end %>
Two issues with your view:
you are using "<%=" where you should be using "<%".
you don't need 'puts'
This should improve your results:
<% #todo_array.each do |t| %>
<%= t %><\br>
<% end %>
I would further consider using some HTML structure to better structure your todo list (instead of using br tag at the end of lines), perhaps an un-ordered list like so:
<ul>
<% #todo_array.each do |t| %>
<li><%= t %></li>
<% end %>
</ul>
Remove the equal sign from your each statement:
<% #todo_array.each do |t| %>
<%= t %><\br>
<% end %>

Rails: link_to method

I have something like this:
<p>
<b>Tags:</b>
<%if #post.tags.count > 0%>
<%= #post.tags.collect {|c| (link_to c.name, c)}.join(", ")%>
<%else%>
Does not have any tags.
<%end%>
</p>
Which gives me
Tags: Java, CSS
Instead of Java and CSS links. What am I missing?
It's because strings in Rails 3 are, by default, not considered HTML-safe. See this blog post about it.
You can manually mark something as safe by calling .html_safe on it, which would make your code like so:
<p>
<b>Tags:</b>
<%if #post.tags.count > 0%>
<%= #post.tags.collect {|c| (link_to c.name, c)}.join(", ").html_safe %>
<%else%>
Does not have any tags.
<%end%>
</p>
But I'd recommend doing this instead:
<p>
<b>Tags:</b>
<% if #post.tags.count > 0%>
<% #post.tags.each_with_index do |tag, i| %>
<%= link_to h(tag.name), tag %><%= ', ' if i < #post.tags.size - 1 %>
<% end %>
<% else %>
Does not have any tags.
<%end%>
</p>
I think html_safe is what you are looking for!
So this would solve the problem (#post.tags.collect {|c| (link_to c.name, c)}.join(", ")).html_safe
I think your tag names should be input by the user, right?
In this case, html_safe is not your first choice, as it gave full trust to the user. And your site would encounter XSS attacks.
The better choice should be sanitize. See the reference here: http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
As you only want to have links, the following line do what you want:
<%= sanitize #post.tags.collect {|c| (link_to strip_links(c.name), c)}.join(", "), :tags => %w(a) %>
Note the use of strip_links(c.name), this removes all the links that input by the user.
Let's assume the tag names are: ["Product", "hi", "bye"]
By just using .html_safe, the following would be shown:
Product, <strong>hi</strong>, <a href='bad_site.com'>bye</a>
But using the mix of sanitize with strip_links, the following is the result:
Product, <strong>hi</strong>, bye
Or you could mix the use of strip_tags with .html_safe:
<%= #post.tags.collect {|c| (link_to strip_tags(c.name), c)}.join(", ").html_safe %>
This simply removes all tags in c.name before you call the html_safe.
I would suggest (and you probably are doing already :D) removing all unwanted tags before storing into the database.

Resources