Apply a class inside paragraph with HAML - ruby-on-rails

I have got a problem with Ruby on Rails template using HAML.
I have no idea how to apply a specific class inside a tag, for example in:
%p My name is John Doe
I want to add a .highlight class to "name" word. How to do this? I only know this way:
%p
%span My
%span.highlight name
%span is John Doe
but of course it is not the best way to do this, I hope so. Any ideas?

No matter what, you have to put the highlighted text in its own element, so your code is pretty close. You don't need to wrap the rest of the text in elements, though:
%p
My
%span.highlight name
is John Doe
This will produce:
<p>
My
<span class="highlight">name</span>
is John Doe
</p>
Edit:
In the case of question marks, you can use Haml's succeed helper method:
%p
= succeed "?" do
What's your
%span.highlight name
This will render:
<p>
What's your
<span class='highlight'>name</span>?
</p>
There are also precede and surround methods, which you can read about here: http://haml.info/docs/yardoc/file.REFERENCE.html#helper-methods
If you'd rather use string interpolation, it's probably be easiest to define your own helper method.
def hl(str)
capture_haml {
haml_tag 'span.highlight', escape_once(str)
}.strip!.html_safe
end
Since this is kind of elaborate, let me break it down from the inside out. First, we need to escape the string with escape_once. This is only necessary if str comes from user input (and so could lead to an XSS attack), but it's good to have in any event. Then we use haml_tag to render the string inside a span.highlight. Then we have to capture this output as a string with capture_haml, since we're using it in interpolation (ordinarily haml_tag writes to the Haml buffer instead of returning a string). Then we use strip! because Haml will render a newline after this, and you said you don't want that. Finally, we use html_safe to tell Rails not to escape the output, since it would break our <span> and we already escaped the input so we know it's safe.
Now you can use the hl method in your interpolated Ruby:
%p
What's your #{hl "name"}?
This will render:
<p>
What's your <span class='highlight'>name</span>?
</p>

Related

How to pre-populate a text-type input field in html via erb/ruby on rails?

I'm trying to get the following line to work in my Ruby on Rails project's erb.html file:
Student City:<input type="text" name="student[city]" value = <%= #student.city %>>
(This whole thing is inside of a form tag)
Everything works fine unless I give value a multi-word value, then it'll cut off everything after the space in the string.
To be specific, if student.city == "San Francisco", my page loads a text field with "San". I've tried changing it to different data types and manipulating the string and it still does the same thing. (Interestingly, trying to print the result after splitting the string into an array will display
["San",
Is this a known bug? Any ideas for a work around? If this is an actual bug with erb, how do I submit a bug report?
I wonder why you don't use Ruby on Rails' form helpers?
Something like:
<%= form_for #student do |f| %>
Student city: <%= f.text_field :city %>
# ...
<% end %>
Read more about form helpers in the Rails Guides.
You need to enclose them with double quotes:
Student City:<input type="text" name="student[city]" value="<%= #student.city %>" >

Rails escapes string inside label tag

I have a label tag, whose content is loaded from a en.yml file.
html.erb
<%=label_tag(:name, t(:name, scope:[:helpers, :form], name: person_name(person))).html_safe%>
person_name is a helper and outputs a string
persons_helper.rb
def person_name(person)
content_tag(:span,
formatted_name(person.name) || t("helpers.persons.default_name"),
class: 'name').html_safe
end
output string from the helper is passed on t method and concatenated as following
en.yml
name: "Person Name: (%{name})"
I want the output to be like
<label for="person">
Person Name:
<span class='name> John Doe </span>
</label>
but Instead I get
<label for="person">
Person Name:(<span class="name">John Doe</span>)
</label>
I understand that it got to do with html_safe, raw and escaping strings but I just could not get it to work!
Thanks!
Call .html_safe on the method call inside the label_tag. E.g:
<%=label_tag(:name, t(:name, scope:[:helpers, :form], name: person_name(person).html_safe))%>
It appears that the I18n.t method does not return a SafeBuffer (i.e. an html_safe string). So you should call .html_safe on the output from this method.
<%= label_tag(:name, t(:name, scope:[:helpers, :form], name: person_name(person)).html_safe) %>
Note the .html_safe call has been moved in one parenthesis from where you had it. This can also be made marginally easier to see by using the block form of the label_tag helper.
<%= label_tag(:name) { t("helpers.form.name", name: person_name(person)).html_safe } %>
Note: I also switched to the "helpers.form.name" method of selecting the I18n translation in this example to further increase readability (but this may be just a personal preference -- so use your original style if you prefer!).
Finally, for security purposes -- so that a user's name doesn't come through unescaped -- you should remove the .html_safe from your person_name helper and add a strict html_escape (or sanitize) so that it looks like this:
def person_name(person)
content_tag(:span,
h(formatted_name(person.name)) || t("helpers.persons.default_name"),
class: 'name')
end
In this form, the content_tag will make sure everything is html_safe except for the content. Meaning that the person.name will come through as is and be escaped as needed. However, this is not needed if the formatted_name method returns an already escaped or html_safe name. Basically the point is that you don't want to blindly mark strings as html_safe when they come from user inputted values because you don't know if they contain script tags or what. Hopefully this didn't confuse. :) In general, only mark strings as html_safe when you are 100% sure that they are actually always going to be safe (i.e. they come from within your system and not from user input of any sort).
Rails translations can be automatically marked as html_safe but using a naming convention. If a translation is suffixed with _html then the string is marked as html_safe, likewise keys named html are also marked as html_safe.
# config/locales/en.yml
en:
welcome: <b>welcome!</b>
hello_html: <b>hello!</b>
title:
html: <b>title!</b>
In the above t('hello_html') and t('title.html') will be html_safe strings and will not require a call to raw or .html_safe where as t('welcome') will not be html_safe and will require calling raw or .html_safe to avoid the html in the string being escaped.
See http://guides.rubyonrails.org/i18n.html#using-safe-html-translations

Is there a way of just having one pair of <% %> in ruby on rails [duplicate]

Sometimes it's more convenient to print in <%%>. How to do it in Rails?
http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-concat
Should be what you are looking for.
E.g. the following statement using concat:
<% concat "Output" %>
is equivalent to:
<%= "Output" %>
In ERB:
The <% %> signify that there is Ruby code here to be interpreted.
The <%= %> says output the ruby code, ie display/print the result.
So it seems you need to use the extra = sign if you want to output in a standard ERB file.
Otherwise, you could look at alternatives to ERB which require less syntax,.. maybe try something like HAML. http://haml-lang.com/tutorial.html
Example:
# ERB
<strong><%= item.title %></strong>
# HAML
%strong= item.title
Is that more convenient?
erb has two method to evaluate inline ruby expressions. The <% which evaluates the expression and the <%= which evaluates and prints. There is no global object to print to within the binding context.
As mentioned by Omar, there is a concat method, which is part of ActionView. This will do what you want.
Unlike a scripting language escape, there is no default output for erb. Since erb is simply a function, and given a template and binding will return a variable, it returns the values of text and functions recursively.
There is hot debate as to how much logic should be allowed in a view, but as little as possible is what most people aim for. If you are putting more code than text in the view, you may want to consider refactoring your code.

converting plain text to html

My rails 3 app receives emails. Some of them are plain text. When the app displays them to the user I want them to be properly formatted. In other word I want to encode plain text into html. For example: "Hello\n\nHello" => HelloHello (or something like it).
Of course I can write my own 4 lines of code but I am sure those 4 lines have already be written, tested and wrapped in some nice method call.
I know I'm a little late, but I actually think the proper solution to this, at least within Rails, is to leverage the simple_format helper method provided from ActionView::Helpers::TextHelper.
Wrap your text in a Pre tag:
<%= content_tag('pre', "Hello\n\nHello") %>
Using #html_safe, let me explain with an example:
If in your controller the variable is:
#str = "<h1>Hi</h1>"
Then in the view:
<%= #str.html_safe %>
#Batkins has the right answer, which should be accepted.
if someone who is still looking,
Converting plain text to HTML
<%= simple_format("plain text") %>
Converting HTML to proper plain text
text.html_safe
The simple_format is TextHelper module so you if you want to use simple_format method in controller
include ActionView::Helpers::TextHelper
in your controller
render :text => "bla bla bla"
it be useful
http://apidock.com/rails/ActionView/Rendering/render

Print in ERB without <%=?

Sometimes it's more convenient to print in <%%>. How to do it in Rails?
http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-concat
Should be what you are looking for.
E.g. the following statement using concat:
<% concat "Output" %>
is equivalent to:
<%= "Output" %>
In ERB:
The <% %> signify that there is Ruby code here to be interpreted.
The <%= %> says output the ruby code, ie display/print the result.
So it seems you need to use the extra = sign if you want to output in a standard ERB file.
Otherwise, you could look at alternatives to ERB which require less syntax,.. maybe try something like HAML. http://haml-lang.com/tutorial.html
Example:
# ERB
<strong><%= item.title %></strong>
# HAML
%strong= item.title
Is that more convenient?
erb has two method to evaluate inline ruby expressions. The <% which evaluates the expression and the <%= which evaluates and prints. There is no global object to print to within the binding context.
As mentioned by Omar, there is a concat method, which is part of ActionView. This will do what you want.
Unlike a scripting language escape, there is no default output for erb. Since erb is simply a function, and given a template and binding will return a variable, it returns the values of text and functions recursively.
There is hot debate as to how much logic should be allowed in a view, but as little as possible is what most people aim for. If you are putting more code than text in the view, you may want to consider refactoring your code.

Resources