Getting proper indentation using XMLBuilder in a helper - ruby-on-rails

I'm attempting to use a view helper to create some dynamic links based on if you're logged in or not.
What I want returned, for sake of easy code readability, is:
<ul class="right">
<li>Login</li>
<li>Register</li>
</ul>
In the view helper I have this Ruby code:
def loginh
xm = Builder::XmlMarkup.new(:indent=>2, :margin=>4)
xm.ul("class" => "right") {
xm.li('class' => 'text') {
xm.text("test")
}
}
end
In the view, the line that calls login helper is already indented 4 levels. Because of this, the first line gets 'skewed', so in the view I have:
<%= loginh %>
Which results in:
<ul class="right">
<li class="text">
<text>test</text>
</li>
</ul>
You can see it works perfectly, except for the first line.
It would appear that the first line is affected by the indent before <%= loginh %> is called.
I can easily remedy this by removing the indentation prior to <%= loginh %> - but in essence I'd be sacrificing code readability for markup readability. Which isn't what I'm looking to do.
Is there any way I could remove the beginning whitespace?

<%= loginh -%> is almost what you want.
The trick is the minus sign in the closing part, which suppresses extra whitespace.
Alternatively, you could pipe the output through HTMLTidy using backticks (the ` character).

Related

What is the meaning of <%%= in Ruby on Rails?

I cannot find it anywhere but in the project I am working with.
It doesn't work in the same way as <%= (I tried to change), but I can't understand the difference.
<span class="option-content" placeholder="<%=t('pages.edit.option')%>">
<%%= content %>
</span>
The ERB dock here says
<% Ruby code -- inline with output %>
<%= Ruby expression -- replace with result %>
<%# comment -- ignored -- useful in testing %>
% a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
%% replaced with % if first thing on a line and % processing is used
<%% or %%> -- replace with <% or %> respectively
this means the
<%%= content %>
will will be replaced with
<%= value of content %>
In short, ERb processes double-percent marks into single-percent marks.
It looks like you're using one layer of ERb templates to generate another layer of ERb templates.
The first layer of ERb doesn't need a variable called content, just the t method:
<span class="option-content" placeholder="<%=t('pages.edit.option')%>">
<%%= content %>
</span>
That first layer is rendered to produce the second layer:
<span class="option-content" placeholder="Edit">
<%= content %>
</span>
As you can see, that is also an ERb template. I expect that something else, later on, takes that second ERb and uses it to render something like:
<span class="option-content" placeholder="Edit">
Hello, world.
</span>

Trouble with looping through array in Ruby on Rails?

I'm learning Ruby and Rails, and the tutorials have been saying I should set everything up in the controller first for what my ERB file is going to need. I'm having some issues doing that.
I'm getting a product catalog from an API and I'm getting back an array. Here's the start of it:
[{"Name"=>"3x4 Vinyl Magnet", "Description"=>"Made of durable high-gloss vinyl. Measures 3x4 inches and has rounded corners. Waterproof and scratch resistant.", "UnitPrice"=>8.99, "ProductCode"=>"Gift65001"
There are more multiple products.
In my controller file I have:
#http_party_json = JSON.parse(#response.body)
#http_party_json.each do |i|
i.each do |x|
#just_products = x['Products']
end
end
#just_products.each do |grab|
#product_code = grab['ProductCode']; #product_code.delete! ';'
#just_names = grab['Name']
#just_prices = grab['UnitPrice']
#just_descriptions = grab['Description']
end
My ERB file is:
<div class="large-12 columns">
<div class="row">
<% #just_products.each do %>
<div class="large-3 columns panel radius" style="height: 600px"><h2><%= #just_names %></h2><br><h3><%= #just_prices %></h3><br>
<p><%= #just_descriptions %></p>
<button id="<%= #product_code %>">Add to Cart</button>
</div>
<% end %>
</div>
It's displaying the last item in the array for each result it's bringing back. If I transfer the grab loop from the controller to the ERB file, it works fine, but I want to learn how to do it correctly.
I should set everything up in the controller first for what my erb file is going to need
I see the trouble... it's a question of interpretation of what the book is trying to say. In your code, this block,
#just_products.each do |grab|
and all the assignments within it is actually not doing anything for you. After it's done spinning through #just_products.each, the final assignment it makes to #just_descriptions is merely the last value of 'Description' in #just_products, which is what you're seeing in your view.
The book merely says to prepare everything that the erb view is going to need. This does not translate to, "assign every possible variable explicitly in the controller". It is perfectly acceptable to pass #just_products to your view and spin through it (via .each) in there.
If you prefer not to do this, your alternate option would be to build arrays of codes, names, descriptions, etc. in the controller. Then spin through each of these in your view. In this case, this line:
#just_descriptions = grab['Description']
would look more like:
#just_descriptions << grab['Description']
There reason it's showing the last one is because you are looping through the array and overwriting the ivar every time. So when you get to the last item in the array you have overwritten each preceding one.
The main thing you want to avoid doing in your view is making SQL queries. Here, you've already loaded everything into an array and that's enough.
<div class="large-12 columns">
<div class="row">
<% #just_products.each do |product| %>
<div class="large-3 columns panel radius" style="height: 600px"><h2><%= product['Name'] %></h2><br><h3><%= product['UnitPrice'] %></h3><br>
<p><%= product['Description'] %></p>
<button id="<%= product['ProductCode'].delete!(';') %>">Add to Cart</button>
</div>
<% end %>
</div>

how to use database field as attribute value in rails template

I basically want to do this:
<% #videos.each do |vid| %>
<div id=vid.location>
...
<% end %>
how do I evaluate vid.locaion and use it as the id attribute?
i've tried the above, id="#{vid.location}" and id="<% vid.location %>" (the last one with and without quotes.
any help appreciated
Easy,
<div id="<%= vid.location %>">
Your first attempt was wrong as you're still in markup - not ruby. In the last one you used <% rather than <%=, so while it was evaluating the getter, it just didn't present it to your view.

'spaceless' equivalent of Django templates in Rails

Notice the readability and balance of:
<li class='aclass anotherclass <%= maybeaconditionalclass %>'>
<a href="<%= some stuff %>">
<%= some other stuff %>
</a>
</li>
which unfortunately produces trailing whitespace inside the link resulting in a ugly trailing underline. Now although less readable I can live with this:
<li class='apossibleclass anotherclass <%= maybeaconditionalclass %>'>
<%= some other stuff %>
</li>
Still, the same problem remains if I now consider this kind of thing:
li.apossibleclass:after {
content: "/";
}
as the whitespace between the closing A and LI gets in the way of what should be sticking to my list item's end. I could only produce that ugly mess as a workaround:
<li class='apossibleclass anotherclass <%= maybeaconditionalclass %>'>
<%= some other stuff %></li>
Django came up with a nice solution: {% spaceless %}, so I'm looking for the equivalent of the {% spaceless %} tag in Rails erb templates.
Yes, that would be an useful feature, and as far as I know, there's nothing like it in Rails. So I've coded it.
# Strip all whitespace between the HTML tags in the passed block, and
# on its start and end.
def spaceless(&block)
contents = capture(&block)
# Note that string returned by +capture+ is implicitly HTML-safe,
# and this mangling does not introduce unsafe changes, so I'm just
# resetting the flag.
contents.strip.gsub(/>\s+</, '><').html_safe
end
This is a helper you can place in your application_helper.rb, and then use like this:
<%= spaceless do %>
<p>
Foo
</p>
<% end %>
... which will result in the output string like
<p> Foo </p>
Sadly, this only works in Rails 3. Rails 2 support for a feature like this will require some dirty hacks to ERb.

Block comments in html.erb templates in rails

How do you comment out html mixed with ruby code?
some text <% ... %> more text <%= ... %>
something else
<% ... %>
In jsp it's real simple: <%-- ... --%>, but I'm unable to find any concise option in rails.
Simple html comments <!-- ... --> do not work: ruby code is still executed and yells errors.
There's an option to use if false with html comments, but it's quite verbose, not to mention IDEs doesn't support it.
There's also an option coming from pure ruby, which surprisingly works.
<%
=begin %>
... html and ruby code goes here
<%
=end %>
It's generally fine, except that it's verbose, weird-looking and none of ruby IDEs I know support it (yep, I like to comment/comment-out with one keystroke).
I'm curious, is there any 'official' of doing this in rails?
Thanks!
Use this for commenting single lines:
<%# your_ruby_code %>
For multiple lines, the following would work:
<% =begin %>
<% ruby_code %>
<% =end %>
What you said would work.
I wouldn't count as a solution, but perhaps enclosing the chunk between an
<% if false %>
...
<% end %>
or if you feel a little dirty, create a helper that simply outputs nothing.
I've never needed it, but I'm stumbled there seems to be no out-of-the-box solution for this.
The =begin approach is annoying because:
It doesn't work for mixed HTML and Ruby (or just HTML) that's on a single line
It's annoying to type
The <% if false %> approach works, but it looks weird and doesn't give anyone else who looks at your code a hint about your intentions.
My solution is as follows:
In application_helper.rb, add a method so:
def comment
end
Then in your view template, you can say:
<% comment do %>Some stuff that won't be rendered...<% end %>
This works because any Ruby method can take a block, but will silently ignore the passed-in block if your method doesn't include a yield.
<%#=
...commented
multiline
block...
%>
For block comments in templates, my text editor (Komodo) finds this variation on #Garfield's recommendation least obnoxious:
<%# A long multiline comment in a rails template ...
# line 2
# and so on ...
# %>
To comment out erb tags use the ruby comment hash symbol before the = sign in the opening tag
<p>
This is some text I want to keep
<%= #some_object.some_attribute %>
</p>
<p>
I want to keep this text but comment out the erb tag
<%#= #some_object.another_attribute %>
</p>
<!--
<p>
I want all of this text commented out including the erb tag
<%#= #some_object.some_attribute %>
</p>
-->
<!--
<p>
I just want this html commented out but I want to keep the erb tag
<%= #some_object.some_attribute %>
</p>
-->
Since you can use <% %> to put a ruby block, it can be certainly used to put in comments into it.
A simpler and elegant solution would look like...
<%
# See! I am a Ruby Comment
# And I am multi-line
# I look like a recognizable ruby comment block too
# and not so complex
# The only drawback with me is the Hash symbol you have to repeat
# But it's the norm, isn't it?
%>
After =begin you do not need to put %>
<%
=begin
code code code code code code
code code code code code code
code code code code code code
code code code code code code
=end %>
Just an addendum to some of the previous answers. I found the =begin/=end solution most useful, but for the sake of beauty I write it like so:
<%
=begin
<p>HTML will be ignored</p>
<%= 'and so will ruby' %>
<p>
<%= 'plus the whole block will be greyed in editor' %>
</p>
=end
%>
Note that since everything is ignored until the =end there is no need to close the =begin tag with %> or open the =end tag with <% (which has also been pointed out in an earlier answer)
I found this to be the most elegant solution to completely outcomment a block of mixed ruby and html code and have it greyed out in my editor as well, as opposed to the <% if false %> solution. Only drawback is that =begin and =end must be placed at the very beginning of the line..
Use a HEREDOC called comment
Pros:
Self-explanatory that this is a comment
Works for erb and HTML tags
Has ok syntax highlighting (as one long string)
Cons:
Weird 3 line closing syntax
No keyboard shortcuts
Code:
The opening tag can be
<% <<-COMMENT %>
the above closing erb tag is just for looks (to match the end),
but don't put anything else there, it may show up on the page
or
<%
<<-COMMENT
%>
Anything here won't run or show up in the browser
<P>
this will not be displayed in the browser
<strong> even in the developer's tools </strong>
</p>
<% 1_000_000_000_000.times do |count| %>
for the <%= count %>'th time, this won't run a trillion times,
this is all just a string
all of these %>, <%, <% end %>, end, do, <!--, won't cause any issues.
but the below opening erb tag is important (if you used any erb tags in the comment).
I have no clue why?
The closing tag
yes it needs to be 3 lines 😟.
I don't know why the opening erb tag is important but it is! (unless you didn't use any erb tags in the comment).
<%
COMMENT
%>
You have to bear in mind where the code is executed. Ruby-style comments work because the Ruby code is executed on the server before it is served to the web browser. This also explains why HTML comments do not work—the Ruby has already been executed.
Doesn't the IDE you're using support creating custom macros for commenting out blocks of code?
You can use both <%if false%> and HTML comments at the same time:
<%if false%><--
stuff to comment out
--><%end%>
The benefits are:
Ruby code is not executed
The commented block has gray color in IDE
The intention is obvious for other developers
Sublime Text's block comment shortcut ctrl+shift+/ notices whether you've selected normal HTML or an Erb tag and puts either the <!--- or <%
=begin %> accordingly.
This is the onlyone that worked for me.
<%
=begin %>
code code code code code code
code code code code code code
code code code code code code
code code code code code code
=end %>
<% %w(
<span title="<%= title %>">hello</span>
) %>
I hope I've just blown your minds!
One way
This is my preferred way.
<%# START COMMENTED OUT SECTION %>
<%if false%><--
your view code here....
--><%end%>
<%# END COMMENTED OUT SECTION %>
You might say, why on earth would you want massive caps locks sentences in your code? The answer is because it's easy to forget (or simply not know) what <%if false%><-- is doing, or what --><%end%> is doing. A sleepy or uncaffeinated developer could easily delete them thinking they were typos, which would not be good! That's why I try to be kind to myself/other developers and make it super obvious. It's not succinct or pretty, but it's very practical and almost foolproof.
Second way
This method is great for being:
Simple
Not idiosyncratic (i.e. uses normally formatted ruby)
Expressive: conveys the meaning of what's happening (someone can easily figure out what it's doing)
Minimal
And here it is:
<%#
multiple
lines
commented
out
%>
The only acceptable solution I ever found to this back-breaking problem was to put a space within the "<%=" to make it no longer register as ruby code, and then comment out the whole block with html comments
Like this:
<!--
<p>
< %= #some_object.some_attribute %>
</p>
<p>
< %= #some_object.another_attribute %>
</p>
<p>
< %= #some_object.some_attribute %>
</p>
<p>
< %= #some_object.some_attribute %>
</p>
-->
Yes, adding the spaces is annoying. But it is the least annoying of all the solutions I've yet seen.

Resources