I've been looking around for a solution to this question for the last couple of days. It's a simple annoyance, but I hate not knowing how to do things...
Environment: Ruby, Rails, rhtml
The Problem: When I iterate a collection in rhtml I would like to reduce the number of <% %> and <%= %> tags I use. The following seems bloated:
Example
<% #products.each do |p| %>
<%= #p.name %>
<% end %>
EDIT: how do I exclude <%= %> inside of a block?
I would much rather do:
<% #products.each do |p|
puts #p.name
end %>
Certain situations could allow for use of either... However, I know that I could do this with jsp:
<% for(int i=0; i<10;i++){
System.out.print(i);
} %>
Thanks in advance for your input.
if you want to be less verbose look at haml, with your example it will be :
- #products.each do |p|
= #p.name
<% #products.each do |p|
_erbout << #p.name
end %>
_erbout is the default name of the variable that ERB (the class that's parsing your .rhtml template) uses to build its output. This is pretty ugly, and feels a bit hacky to me, but it works.
Use print instead of put.
Several other possibilities, depending on the context, if your view code seems too bloated:
Use partials. E.g.:
in your main file:
<%= render(:partial => "product", :collection => products) %>
and in the partial, just use:
<%= product.name %>
Now this seems contrived for a simple example such as this but assuming something more complex it abstracts away the looping and makes the code clearer.
Use helper methods
You could also try using something like haml to clean up the templates (along with helpers and partials).
You're going to have to use a <%= inside such a block. You can achieve the readability you want by using a <%= with a block:
<%= #products.map do |p|
p.name
end.join("\n") %>
Related
<% consents_checkboxes.each do |checkbox| %>
<%= checkbox.html_safe %>
<% end %>
Hello there,
can i give them a class while looping through them? I can't get it to work and tried several different ways.
This is something I would like to achieve
<% consents_checkboxes.each do |checkbox| %>
<%= checkbox.html_safe, class: 'checkbox' %>
<% end %>
thank you
You can only do it with an element. What you want to do is:
<% consents_checkboxes.each do |checkbox| %>
<p class="checkbox"><%= checkbox.html_safe %></p>
<% end %>
Of course, you can use another element (span, div etc.).
What's on consents_checkboxes? You should provide more context when you ask for something...
It looks like you have strings with the html code, right? you will have to parse the string with something like nokogiri and add a class
<%= Nokogiri.parse(checkbox).add_class('checkbox') -%>
Or you could modify the process that generates that consents_checkboxes to include the class you need. Maybe there's better options, but with only that information it's really hard to tell.
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 %>
In the Rails views, I regularly find lines like:
<%= my_var %>
What if I had a slightly more complex situation and I needed to trigger the printing with plain code instead of <%= %>?
Example:
<% .....
puts my_var
%>
I guess is a silly question but bear with me, I'm a ruby beginner.
Look at documentation of ERB
In <% %> you put expressions that are not for printing out.
In <%= %> you put code for printing out.
Example:
<% if #cost < 10 %>
<b>Only <%= #cost %>!!!</b>
<% else %>
Call for a price, today!
<% end %>
You can use helper method which is much more cleaner.
I'm making a form for an Order object, and the order has many Products, via a join table called OrderProducts. So, we've got something like this:
<% #order = Order.new %>
<% form_for #order do |f| %>
<% #products.each do |product| %>
... want to iterate over products here to build up "order[product_ids][]", with one checkbox per product
<% end %>
<% end %>
Usually for each product i would have a check_box_tag, saying
<%= check_box_tag "order[product_ids][]", product.id, #order.product_ids.include?(product.id) %>
But this, while working fine, always feels like a bit of a cop out. Is there a way i can do it with the f.check_box syntax? Important note - on the project in question I'm working in Rails 2.2.2, so a solution that works in rails 2 would be ideal.
Rails <= 2.x (original)
<% #products.each do |product| -%>
<% fields_for 'product[]' , product do |product_fields| -%>
[...]
<%= product_fields.check_box :id %>
<% end -%>
<% end -%>
Rails >= 3.x (updated)
<% #products.each do |product| -%>
<%= fields_for 'product[]' , product do |product_fields| -%>
[...]
<%= product_fields.check_box :id %>
<% end -%>
<% end -%>
I know the author was looking for version 2 answers, but this is the top hit for google and I though I would update:
One can do this ( I'm using 4.0, don't know how far back it goes ):
<%= form_for #order do |form| %>
<%= form.collection_check_boxes(:product_ids, Product.all, :id, :labeling_method ) %>
<% end %>
For more info: http://edgeapi.rubyonrails.org...
I've done a number of multi checkbox forms over the years and different Rails version. Rails has never provided any really clean way to do it, but the "cop out" solution you came up with is pretty good isn't it? It's one line, it's explicit, and as long as the list of products is reasonably short it will perform adequately.
To answer your specific question, f.check_box will never work for this. It's just short hand for the check_box_tag, but none of the semantics apply. If you want to go Rails native, the only possibility I think is to use nested attributes. Part of the problem is that there is not one obvious way for this type of thing to work. Rails core went through a lot of planning and feedback to come up with nested attributes as they exist, and though they seem a bit obtuse, they capture the most common use cases quite elegantly. But nested attributes were introduced in Rails 2.3, and besides they will introduce quite a bit of conceptual overhead for something which sounds like it doesn't need the complexity.
There are also some plugins that provide helpers for this, although I haven't used any in a long time (since Rails 2 era actually). My impression is that they too are overkill unless you have many forms that make use of this pattern.
In short, I think you should go ahead with your existing solution.
formastic gem
check_boxes option is very good to implement multiple checkboxes
like
f.input :yourcolumn, :as => :check_boxes, :collection => your_collection
Newbie here coming from Microsoft MVC3+razor.
Say I had:
<% if foo %>
<%= bar %>
<% end %>
Is there a way I can have:
<% if foo
magic_function_that_goes_to_output_buffer bar
end %>
Does this function exist?
Edit:
To be absolutely clear, I am looking for a solution I can use multiple times within <% %> blocks. Having a solution between <%= %> blocks just moves the problem.
An answer of "No" is acceptable as then I can stop being annoyed by it and just move on.
Solution accepted:
My application_helper looks like
def out(content)
#output_buffer.safe_concat(content)
end
My view looks like
prevReview = nil
#review.each do |review|
out render :partial => 'review',
:locals => { :review => review, :showDate => (prevReview.nil? ? true : prevReview.updated_at === review.updated_at) }
prevReview = review
end
Yes there is a way.
But before I tell it, please don't do this unless you have a really good reason. This is because you'll be tied to an implementation detail that may change anytime.
Just post a new question that target your specific problem, you'll certainly get good answers.
Here it is:
<% if foo
#output_buffer.concat("any string will do")
bar = call_what_you_want
#output_buffer.concat(bar.to_s)
end
%>
Okay, this works well on Rails 2.x but with Rails 3 you'll concat to a safe output buffer so you should maybe call #safe_concat instead of #concat on the #output_buffer variable.
It does, try this:
<%= bar if foo %>
Edit:
You can do that too:
<%= if true
"true"
else
"false"
end %>
But if you have much logic involved, you should better use a helper. So in you helper file:
def magic_function_that_goes_to_output_buffer(condition)
if condition
"true"
else
"false"
end
end
In your view:
<%= magic_function_that_goes_to_output_buffer(foo) %>
Maybe you want to look at the haml. With haml code looks cleaner and stylish.
<% if foo %>
<%= bar %>
<% end %>
This erb code transforms to:
- if foo
= bar
That's all. Couple of useful links haml site and haml-rails plugin page. Good luck!