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.
Related
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.
I'm using the liquid gem and a wysiwyg editor for user posts. I'm trying to replace some of the content submitted before it is displayed. To do this I have tried .gsub but it isn't working at all
<% template = Liquid::Template.parse(#category.template) %>
<% render = template.render(#keys_values_hash) %>
<% content = render.gsub!('data-imgslap=', 'data-slap=') %>
<% content.html_safe %>
The content is displayed fine and it all works but the text isnt replaced from gsub
I want it to just replace one thing so I know it works. But once that works I want to replace a couple of things. How would I use gsub to replace say 'text1', 'replacement1' and 'text2', 'replacement2' and why wont it work for just one replacement like I have setup now.
The data is stored as a string and grabbed from the db if that matters.
Update
Got it working. forgot to add the equal sign on <%= on content.html_safe %>
still got the problem of having 2 gsub changes on the one string here is what I have which doesnt change any coding
<% template = Liquid::Template.parse(#category.template) %>
<% render = template.render(#keys_values_hash) %>
<%
replacements = [ ['data-imgslap=', 'src='], [' src="http://i.imgur.com/bEDR9dc.png"', ''] ]
replacements.each {|replacement| render.gsub(replacement[0], replacement[1])}
%>
<%= render.html_safe %>
Got this from another question on stackoverflow but it doesn't work for me.
Generally, don't use multi-line statements in ERB. Make it two lines. And use gsub! to change the render object.
<% replacements = [ ['data-imgslap=', 'src='], ['src="http://i.imgur.com/bEDR9dc.png"', ''] ] %>
<% replacements.each {|replacement| render.gsub!(replacement[0], replacement[1])} %>
<%= render.html_safe %>
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.
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.
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 %>