Rails .map produces unwanted ["\n"] - html

I got the following lines in my view:
<p><%= #runnings_past.map do |f| %>
<%= f.title %>
<% end %>
</p>
which works just fine in the console --> output:
2.1.2 :076 > #runnings_past.map do |f|
2.1.2 :077 > f.title
2.1.2 :078?> end
=> ["Murtenlauf"]
2.1.2 :079 >
But when I use it in the view as seen above, I get an expression like this:
Murtenlauf ["\n"]
Where does the ["\n"] come from?

You are using the wrong iterator. You want to use each instead of map. Map creates a new array where each element is the result of each iteration in the block. While each simply calls the given block once for each element in the array.
In addition, as pointed out by #JTG, you want to remove the =. You only need = for showing output. You don't need it for logic.

<%= #runnings_past.map do |f| %>
<%= f.title %>
<% end %>
Should actually be
<% #runnings_past.each do |f| %>
<%= f.title %>
<% end %>
Notice the lack of = (in addition, I changed map to each because you're just iterating through the array)
<%= means evaluate the code and insert the result into the html structure. So what you were doing was evaluating the .map and putting the result into your html. So you would iterate through the #runnings_past code, place the f.first into the html (which is what you want) but then when you were done with that, you were placing the result of the mapping (which apparently was an array with a string return character) into the html afterwards.

Related

eRB and multiple statements syntax?

I have the following in an html.erb file, using link_to to get a hyperlink and t() to internationalize my text. But it looks very clunky:
<p><%= t('session.new_user') %><%= link_to(t('session.signup_now'), signup_path) %></p>
Splitting onto multiple lines seems wrong since the text will all appear on the same line on screen but is there a better syntax to avoid the two consecutive <%= %> blocks?
I would probably go for line breaks:
<p>
<%= t('session.new_user') %>
<%= link_to t('session.signup_now'), signup_path %>
</p>
or you could set variables before the actual code
<% new_user_text = t('session.new_user') %>
<% link = link_to t('session.signup_now'), signup_path %>
<p><%= new_user_text %><%= link %></p>
or you could set instance variables in the controller. I wouldn't like that for view stuff like this.
Extra: if you like tidy code you may like haml
%p
= t('session.new_user')
= link_to t('session.signup_now'), signup_path
now it is actualle readable!
You can add a hyphen before the closing tag to prevent a newline being appended to the output.
<% ... -%>
Please note that this feature is Rails specific.

Using .html_safe in an each loop

I've been running into issues with using .html_safe within .each loops. Here is how I may have something set up...
class Players < ApplicationController::Base
def index
#players = Players.all
end
end
In the view:
<% #players.each do |player| %>
<div>
<%= player.stat_code.html_safe %>
</div>
<% end %>
Now the stat_code would be a long HTML chunk of code... (I don't have an example for this case) But it's HTML.
Using the .html_safe does not seem to do anything while it's in a .each loop. Why does nothing happen and what other solution would you recommend?
Note: I also read that using .html_safe is bad! For this particular case I don't care.
I managed to accomplish my issue by setting up the view with sanitize instead of .html_safe like so...
<% #players.each do |player| %>
<div>
<%= sanitize player.stat_code %>
</div>
<% end %>

Issue with Nested Form rendering

I have a rails 4 app that has a form that looks like:
<%= form_for #store, :html => {:multipart => true} do |f| %>
<%= f.fields_for :products do |product| %>
<%= render partial: "edit_product_fields", locals: {product:product} %>
<% end %>
<%= f.submit %>
<% end %>
and the edit_product_fields partial looks like:
<select>
<option value="Textbook" <% if product.type_of == "Textbook" %>selected<% end %>>Textbook</option>
<option value="Magazine" <% if product.type_of == "Magazine" %>selected<% end %>>Magazine</option>
<option value="Book" <% if product.type_of == "Book" %>selected<% end %>>Book</option>
</select>
When I have the code like this, I get the error:
undefined method `type_of' for #<NestedForm::Builder:0x00000102304f78>
but if I change the render line to (I just made it less explicit by taking out partial:):
<%= render "edit_product_fields", locals: {product:product} %>
I get the error:
undefined local variable or method `product' for #<#<Class:0x0000010235a248>:0x0000010684b3c0>
In your first code block, you have a Builder object being stored as product.
Fortunately, Builder provides an object method so you can access the actual object that it's representing in the form:
<select>
<option value="Textbook" <%= 'selected' if product.object.type_of == "Textbook" %>>Textbook</option>
<option value="Magazine" <%= 'selected' if product.object.type_of == "Magazine" %>>Magazine</option>
<option value="Book" <%= 'selected' if product.object.type_of == "Book" %>>Book</option>
</select>
Well type_of is not a ruby method. It looks like it's an attempt to type check though... But type checking is generally frowned upon in duck-typed languages. At any rate, we can take advantage of a Rails Form Helper instead and make this code a one-liner. But first...
The reason the render is complaining about undefined local variable or methodproduct'` after your change is because the render call expects either the first argument to be a partial name and the second to be a hash of locals:
<%= render "partial_name", local1: "a", local2: "b" %>
... or it expects the the whole thing to be a hash:
<%= render partial: "partial_name", locals: { local1: "a", local2: "b" } %>
Now, back to the form helper.
What you're looking for here is the select helper. This makes the following possible:
<%= product.select :type_of, %w[Textbook Magazine Book] %>
And this will render all of the same html as you've put into your _edit_product_field.html.erb partial. So you should probably just get rid of the partial to save on rendering time and put this directly into your form.
One other, minor point. It may be less confusing to call the fields_for block variable product_form instead of product. This is to help keep in mind that this is not a Product object you're dealing with, but rather a Form Generator object. Also, you don't need to specify :multipart => true in Rails 4 forms -- Rails knows to make the form multi-part if you have a file upload element within the form body.
So putting it all together:
<%= form_for #store do |f| %>
<%= f.fields_for :products do |product_form| %>
<%= product_form.select :product, %w[Textbook Magazine Book] %>
<% end %>
<%= f.submit %>
<% end %>

How to not show a line break when blank?

In my Ruby app I'm using the following code in my view:
<% if post.image.present? %>
<%= image_tag post.image_url(:thumb).to_s %>
<% else %>
<%= "" %>
<% end %>
If there's no image then it shows a blank which works fine.
The problem is that I do not want to show a line-break. Instead of <%= "" %>, is there something I can use to do that?
I'd do it like this. Instead of a massive if/else statement, use the Ruby one-liner, and instead of an empty string, don't add anything if it's null:
<%= image_tag post.image_url(:thumb).to_s if post.image.present? %>
Note: If it's still adding a line-break, that's probaby something in your CSS. Nothing about this code should give you a line break.

Inserting rails into HTML file

When writing an HTML file, why use <%= INSERT RAILS HERE %> vs. <% INSERT RAILS HERE %>
<%= %> emits a string, <% %> runs code.
On the pedantic side, you're writing an ERb template, not an HTML file--the syntax is the same whether it's a template for HTML, JS, or whatever.
The ERB docs provide additional (but not complete) information.
<%= %> will return value and display in your page. Assume that you have person.name = 'Dark'
<%= person.name %>
will display Dark in your web page.
<% %> will not return any value to your page. It just embed simple ruby code. Usually used with `control statement'.
<% if person.present? %>
<span><%= person.name %></span>
<% end %>
When we use <%= %> it simply displays the value returned, on the html page.
<% %> executed the code but doesn't dispaly it on the html page.