What is the difference between <%= and the "puts" command in rails? - ruby-on-rails

I have a segment of code:
<% #public_address.each do |key| %>
<%= key["address"]["address"] %>
<% end %>
This displays the keys properly, but this code
<% #public_address.each do |key| %>
<% puts key["address"]["address"] %>
<% end %>
displays nothing. What gives? What's the difference between the two?

The <% %> and <%= %> are used in erb to execute ruby code when rendering a template.
Erb is the default template engine in rails.
Difference between <% %> and <%= %>
<% %> Will evaluate the ruby code it contains, but "silently".
Meaning that no output is going to be printed on the rendered page.
<%= %> on the other end, evaluates the ruby it contains and
renders the result on the rendered page.
What's the difference between <% code %> and <%= code %> in Rails erb?
What's puts?
Puts is simply a method from Ruby that is used to print a string at runtime. It has nothing to do with erb templates.

In your first bit of code <%= key["address"]["address"] %>, the <%= %> is rails syntax for evaluating the code inside and returning the value.
In your second bit of code <% puts key["address"]["address"] %>, you use <% %>, which doesn't return an evaluated rails statement. Furthermore, puts is a method that outputs whatever follows it to the stout object. In a command line program, that means printing out to the terminal screen, but in a web app you aren't working with a terminal screen. You are working with controllers and view templates, so it is necessary to use the evaluative <%= %> if you want to return values that will be displayed in the view.

Related

Rails different output if block is given inline or over multiple lines

I'm having trouble finding out what I did wrong or how to achieve the same result.
What I'm trying to do is to print the array #attributes in a rails view.
This is not working:
<% #attributes.each do |element| %>
<%= puts element.to_s %>
<% end %>
But this is:
<%= #attributes.each { |element| puts element.to_s }%>
I've also played around with putting everything in the first statement in <%= %> without any success.
Aren't those two statements exactly the same?
Also, if you could help me out - how would you iterate over the array and insert a new line after each item?
Thanks in advance!
Alex
puts does not actually output to the ERB buffer. It outputs to STDOUT and returns nil. If you want to iterate through the records and output you would do it by:
<% #attributes.each do |element| %>
<%= element.to_s %>
<% end %>
The <%= %> ERB tags output the return value of the expression into the buffer. If you wanted to do this with a non-printing ERB expression you would need to use concat:
<% #attributes.each { |element| concat element.to_s } %>
Aren't those two statements exactly the same?
No. The output is actually the same as:
<% #attributes.each do |element| %>
<%= nil %>
<% end %>
And
<%= #attributes %>
Rails uses the ERB templates to render the views or say generate html documents for the browsers amongst others.
ERBcopies the text portions of the template directly to the generated document, and only processes code that is identified by markers. There are mostly two types of markers <% %> and <%= %>.
A tag with an equals sign indicates that the 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.
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 into the output at the point of the scriptlet.
<% #attributes.each do |element| %>
<%= puts element.to_s %>
<% end %>
With your example above you're telling the renderer to put whatever is the result of the expression in the second line, which is the output of the element.
Whereas here <%= #attributes.each { |element| puts element.to_s }%> you are asking rendered to put the #attributes object/variable along with the individual output of whatever is inside in #attributes variable which explains the difference in your output results.
PS you can avoid both puts and to_s from <%= puts element.to_s %> because whatever is inside <%= %> gets to the HTML document as a string itself.

Comments from post not displaying correctly in rails

Been trying to set up a regular blog in Ruby on Rails, and finally got the comment system to work within a post. However, when I loop through each comment and try to output the comment's title it displays this,
awef [#<Comment id: 6, title: "awef", link: nil, campaign_id: 5, user_id: 1, created_at: "2015-09-24 09:46:43", updated_at: "2015-09-24 09:46:43">]
Instead of just the title. How can I fix this?
The loop in your view should be something like this:
<% #blog.comments.each do |f| %>
<%= f.title %>
<% end %>
Please check you are using the right angular parenthesis (<%= %>) and not placing p puts or inspect commands inside them.
Edit:
Now that you show use the code, the problem is in the first angular parenthesis: should be <% not <%=. The first is for the logic, the latter to output erb code.
<% #blog.comments.each do |f| %> # remove "="
<%= f.title %>
<% end %>
<% ... %>: Executes the ruby code within the brackets
<%= ...%>: Executes the ruby code and show the executing result in webpage
Classic mistake, it's because you're using <%= ERB output tags for the .each loop. You can view more information on how to write correct ERB here.
You need to replace your <%= output tags with standard ERB tags <%:
<% #blog.comments.each do |f| %>
I was stung by that one myself when I was starting out.
The problem you have is probably the = in your each statement.
Try to use this:
<% #blog.comments.each do |f| %>
<%= f.title %>
<% end %>
Notice the removed = at <% #blog.comments.each do |f| %>
The reason is as the <%= %> always prints while <% %> only executes the code.

In a rails view, how can I send output to view besides <%= %>?

Short version:
It seems weird to me to have rails code like, say,
<% if #list.empty
%><%= val %><%
end %>
Is there some way to do something like this?
<% if #list.empty
some_display_function_i_wish_existed val
end %>
Long version:
I have a model, tweet.rb, that overrides to_s. The to_s works fine.
I have a view that needs to output to_s for each tweet in #meme.tweets .
I've observed the following:
<% #meme.tweets.each do |tweet|
tweet
end %>
Result: no output
<% #meme.tweets.each do |tweet|
puts tweet # or tweet.to_s does the same thing
end %>
...Result: no output
<%= #meme.tweets.each do |tweet|
tweet
end %>
...Result: output is entire inspection of each tweet, not to_s
<%= #meme.tweets.each do |tweet|
puts tweet # or tweet.to_s does the same thing
end %>
...Result: output is entire inspection of each tweet, not to_s
<% #meme.tweets.each do |tweet| %>
<%= tweet %>
<% end %>
...Result: works as intended (outputs result of to_s for each tweet). So does:
<%= #meme.tweets.collect do |tweet|
tweet.to_s
end %>
...Result: works as intended.
I come from a PHP background, and don't really understand the rules here.
I know I can do it the way I did in the last example.
But could someone explain why none of the other examples work as I intend?
It seems to me that the rules APPEAR to be:
1) <%= something %> will take that thing, call to_s on it, which will default to inspect if not overridden.
2) <% something %> will execute something
Is there a way to use 2) <% %> to send output to the view?
Or is it against the rules to have <% %> tags that span multiple lines of ruby code at all?
<%= code %> will print to the the output the result of the inner code. <% %> won't print anything, it just evaluates the inner code.
That's why the first example doesn't work. On the second example you expect the puts to print the tweets, but puts doesn't print on the same buffer... (you'll see the tweets printed on the rails console instead).
On 3rd and 4th example you are printing the collection as an object (#meme.tweets.each returns an Enumerable and ERb call #to_s on that) and not the code inside the block.
The 5th form is correct. That's what you'll normally do.
The 6th form is in some way correct too. There you are iterating a collection, calling #to_s on each element and then collecting them on a new array, that gets printed to the output (but you are printing an array of strings, not just one big string).
you can get a similar result with #join. (It returns a string created by converting each element of the array to a string)
<%= #meme.tweets.join %>
<% %> are used when you do not want the Ruby code you're executing to output anything. The <%= %> tags are used when you want to output something. This is why your example using <%= %> and tweet.to_s works as intended.
If you don't specify which attribute you want to output, then yes, puts will display the whole object. If for example, you had a message attribute on your tweet object, writing tweet.message (inside of a <%= %>, of course) would output just the message attribute of that tweet.
The direct answer is the concat function, eg:
Hi, my name is <% concat("Shelvacu") %>.
which is the same as
Hi, my name is <%= "Shelvacu" %>.
Which both output Hi, my name is Shelvacu.
Think of it like this: An erb template is parsed, transformed into valid ruby code, and then that ruby code is run*. Everything that is not inside <% ... %> is converted to concat("..."), <% statement %> is converted to statement, and <%= statement %> is converted to concat(statement.to_s).
So when ERB sees
1 + 2 = <%= 1 + 2 %>
<% puts "hello" %>
<% #meme.tweets.each do |tweet| %>
<%= tweet %>
<% end %>
that code is then translated to*
concat("1 + 2 = ")
concat((1 + 2).to_s)
concat("\n\n")
puts "hello"
concat("\n\n")
#meme.tweets.each do |tweet|
concat(tweet.to_s)
end
* This is an oversimplification, ERB does much more so that errors point the right line, statements don't merge with eachother in unexpected ways, and I didn't even mention <%- ... %>. However, this should be a decent mental model for understanding whats happening when you write code in ERB.

Why is Rails' ERB rendering output from this template code?

I'm using Rails 3.0.3, and the following template (with a .html.erb extension):
<% "one"; "two"; capture do %>
Three
<% end %>
Is rendering as:
one
Why is this? It doesn't seem like it should render anything, since I didn't use <%=
EDIT
Since there seems to be some confusion, here is a reproduction that more closely resembles the actual template code that I'm debugging:
<% my_string = "" %>
<% my_string << capture do %>
Hello
<% end %>
<%= my_string %>
This is rendering as:
Hello Hello
Because for some reason, the captured output is being appended to my_string AND being rendered, instead of just the former.
You're using the rails capture helper but your syntax is wrong. I don't know why it's printing out one. In rails 3.4 it doesn't print out anything.
Here's the right way to use it
<% #number = capture do %>
three
<% end %>
this is some html and here is my <%= #number %>
The html that will be rendered is
this is some html and here is my three
Since your syntax is wrong I wouldn't worry about why "one" is showing up. Instead I'd focus more on using the capture helper correctly.
Edit:
Your second (edited) example is not the same as your first one. Here it is with line numbers and a slight change to the last line so you can see what's going on.
1. <% my_string = "" %>
2. <% my_string << capture do %>
3. Hello
4. <% end %>
5. before <%= my_string %> after
The result is Hello before Hello after. So line 3 is being rendered, then line 5 is being rendered with my_string containing the value Hello.
If you change it to this
<% my_string = "" %>
<% my_string = capture do %> <!-- changed << to = -->
Hello
<% end %>
before <%= my_string %> after
Then the result is before Hello after.
So what does this all mean? When you use << it's screwing up the capture method and it's rendering stuff that's inside the capture block even though normally you don't expect it to.
Basically, you can't do what you're trying to do here, at least not with your current syntax.

Why the use of both <% and <%= in the views?

If I write something like:
<% if signed_in?.blank? %> or <%= link_to "Sign Up", sign_up_path %>
What is the difference between the two signs of <% and <%=?
Why make it this way instead of using just one for simplicity?
When do I know I need to use <% over <%=?
<%= puts the return value of the code inside to the page.
<% just execute code.
Here is the good guide about ERB http://api.rubyonrails.org/classes/ActionView/Base.html
<% %> Simply executes the statement(s) inside that block, whereas <%= %> will output the result of the statement.
So for example, with the <% if signed_in?.blank? %>, the ruby interpreter just executes that code and checks if signed_in is blank.
The <%= link_to %> statement will actually generate HTML.

Resources