Have trouble implement the variable loop in haml file - ruby-on-rails

I use ruby on rails to get some variables and suppose to send them in email format to some email address.
%div
- #msg.each do |line|
%p = "#{line}"
%br
The msg is the string array I passed in and would like to get each element in separate line. How can I achieve that. The above code won't work.

One of the key things of coding HAML is you really are only going to have one item per line, plus you automatically get a div tag as the default tag. So you might as well add a class to your div to differentiate it. Additionally, make sure your indentation is correct:
.messages
- #msg.each do |line|
%p= line
You don't really need a br because the p will break for you, and following a tag with '=' will automatically give you the interpolation.

Related

Properly Escaping a String inside a View

I've read in multiple places that as of Rails 3 you no longer have to use html_escape "some string" to actually escape a string in a view and that simply writing <%= "some string" %> would escape the string by default. However, I cannot find this information in the docs. I read through the XSS in the Rails guides section that stated this:
https://guides.rubyonrails.org/security.html#cross-site-scripting-xss
As a second step, it is good practice to escape all output of the application, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). Use escapeHTML() (or its alias h()) method to replace the HTML input characters &, ", <, and > by their uninterpreted representations in HTML (&, ", <, and >).
Then I see several blogs that state that it is escaped by default. For example: https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/
https://dzone.com/articles/preventing-cross-site-scripting-vulnerabilities-wh
Found it:
https://guides.rubyonrails.org/3_0_release_notes.html
"7.4.3 Other Changes
You no longer need to call h(string) to escape HTML output, it is on by default in all view templates. If you want the unescaped string, call raw(string)."
escapeHTML() (or its alias h()) are from CGI::escapeHTML, which is a Ruby API implementation. If you aren't using Rails you still have a way to escape HTML. Rails may do some automagical handling of HTML in ERB files for display, and that is what you are probably referring to with html_escape "some string" and <%= "some string" %>. I think you are possibly confusing html_escape which you might need when displaying urls and such that are stored in the DB and you want the ERB processor to not mess it up? I know sometimes, particularly in .js.erb files I need to escape some things to get the result I was expecting. This is different than sanitizing. It seems in your example they are referring to something that you might accept and then redisplay, like a search string. If you put <i>hello</i> into a search box you would want to sanitize the input before passing it to the back end, or if you are using some javascript to filter you might want to escape it both for security reasons and to let it re-display correctly in the search box after you've filtered.
Edit: I was not able to find the answer to your comment in the ri doc either. But I tried:
<%= "<b>hello</b>" %>
<%= h("<b>hello</b>") %>
And got the same result in the browser:
<b>hello</b>
<b>hello</b>
So if you are asking if it is true, then I would say yes.

Rails 4: how to insert line breaks in text_area?

I have created a blog in rails. I'm a beginner and got quite far, but now I'm stuck with a seemingly minor detail: I can't seem to format the posts (articles).
Here's the relevant part of my show.html.erb:
<p>
<strong>Content:</strong>
<%= simple_format (#article.content) %>
</p>
When I write something and insert html-tags, they are not recognized as such. What am I doing wrong?
Rails will automatically remove html tags to prevent someone from injecting code into your webpage (e.g. malicious javascript)
If your users cannot enter data into #article.content and it's always safe then you can flag it as safe usng the html_safe method.
<%= (simple_format (#article.content)).html_safe %>
Can you post the article content for reference? If I had to guess, I'd imagine Rails is escaping the html tags and inserting them as plain text (so the output looks like: Article content !
Take a look at Rails' helper methods like content_tag (http://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag) and concat (http://apidock.com/rails/ActionView/Helpers/TextHelper/concat) and consider using those to help with generating the appropriate html tags.
An issue to be concerned with is who's going to be supplying the content. For example, if you're writing an application that other people will use, you want to make sure any html give you is escaped to avoid XSS attacks. In that case, you'll want to spend some time reading about how to properly sanitize user input.
You can now specify the tag it gets wrapped in (defaults to p) like so:
<%= simple_format (#article.content, {}, wrapper_tag: "div") %>
or
add white-space: pre-line style.
It will display \r or \n (enter) in user input as a new line.
for more info:
http://apidock.com/rails/v4.0.2/ActionView/Helpers/TextHelper/simple_format

Ruby on Rails: string method - how to recognize "enter" and re-display it?

I get the data from what other people inserted via a "textarea" in ruby on rails.
They must have clicked "enter" a couple of times. I saved this string data as a variable #input. But if I tried to display it by typing <%=#input%> , then all sentences are connected to together without a clear border that was meant to be there, seeming the enter is not recognized as an "enter".
I think there is a sure way to do it correctly and do you have any suggestion that I can display as the way that input users wanted to display? :)
Looking forward to seeing the opinion from the experts!!
What you're referring to is called newlines or line breaks. Rails got a helper method simple_format that will replace single newlines with <br /> tags and double newlines will wrap the previous string in a <p> tag
<%= simple_format #input %>
If you just want every newline character replaced with a break tag you could do it manually by substituting the \n character:
<%= #input.gsub("\n","<br />") %>

Can Haml omit tags where the Ruby content evaluates to nil?

If I have a line in a Rails template that evaluates to nil, is there a way to have Haml not bother to generate output for that line rather than create an empty tag? For instance given this:
%h4= #my_hash[:optional]
...imagine that there's no data for that hash-key. I don't want to end up with:
<h4></h4>
I'd like no output at all from that line because empty tags can still affect page layout, particularly if you're using something CSS-heavy like Bootstrap.
I can write this everywhere:
-if #my_hash[:optional]
%h4= #my_hash[:optional]
but it's long-winded and ugly.
(It seems like lots of people would want to do this, but I couldn't find any mention of either a way to do it in the Haml docs, or people on SO or elsewhere asking how it could be done. So clearly everybody already knows how to do it except me, right?)
Update: Thanks for the suggestions. The thing is, it doesn't seem to matter what you put after the equals sign here:
%h4= amazing_intelligent_helper_method_but_sadly_too_late()
because Haml has already decided to output a tag at that point, the only question is what goes in the tag? If the expression after the equals sign evaluates to nil, Haml doesn't put any content in the tag - but it still outputs the tag itself.
%h4= nil #output: <h4></h4>
%h4= '' #output: <h4></h4>
%h4= false #unexpected output: <h4>false</h4>
%h4= #Haml::SyntaxError 'There's no Ruby code for = to evaluate.'
So at the moment, I don't have a one-line way of omitting empty tags. But surely I'm not the only one who wants to do this? When you look at some of the esoteric options Haml supports, I'd have really expected this feature to already be in there somewhere.
Just append the condition to the line ala Ruby statement modifiers:
%h4= #my_hash[:optional] if #my_hash[:optional]
Still long winded but at least its on one line now.
Here are some other techniques that were discussed but they're not any shorter or prettier: HAML: Create container/wrapper element only if condition is true
Try this code
%h4= #my_hash[:optional] unless #my_hash[:optional].blank?
Even though this is my question I thought I'd suggest a semi-OK-ish answer I've just thought of in the hope that someone will look at it and say 'Aha! I can do better than that.'
I could put this in the view
!= h4_if #my_hash[:options]
and I throw this in my helper file:
TAGS_TO_DELETE_WHEN_EMPTY = ['h1', 'h2', 'h3', 'h4', 'p', 'span']
TAGS_TO_DELETE_WHEN_EMPTY.each do |tag|
new_method_name = (tag + '_if').to_sym
define_method new_method_name do |content = nil|
"<#{tag}>#{content}</#{tag}" if content
end
end
then I only get an h4 tag if there's content for it. I can use these little conditional helper methods, coupled with Haml's unescaped ruby evaluator '!=', to get what I'm looking for. Downsides include: even though it's very concise in the view, and easy to extend, it doesn't look much like regular Haml. Also, I'm not 100% sure it won't upset Haml in some way if I use much of it.
Plus I'm still hoping someone will tell me there's an option in Haml to not output empty tags, because then I don't need to write any additional code at all (which is my favourite solution to problems).

how to create a strong element inside a p

In haml, how do I render the following incredibly basic HTML:
<p>Results found for <strong>search term</strong>
where 'search term' is actually a Ruby variable called #query?
I'm trying the following,
%p results found for <strong>= #query</strong>
But that renders = #query literally. If I try:
%p results found for <strong>
= #query
</strong>
then the query term renders correctly, but is on a new line.
Also, I'm wondering if there's a better way to render <strong> in haml, while keeping everything on the same line.
I'm aware of the haml documentation, but as far as I can see there isn't an example of using a simple inline Ruby variable.
-----UPDATE-------
The following code works, and shows how to use a variable that's not within tags:
%p
= #trials_found_count
results found for
%strong= #query
But I find it really unreadable - it's hard to tell that it renders as just one line of HTML without adding a comment above.
Is there a way I can put all this code on a single line? Or is this just how haml works?
HAML is whitespace delimited. Nested tags go on the line below and one level in from the tag above. Embedded Ruby from which you want to display output is opened with an '='. Embedded Ruby which you don't want to display such as the start of loops uses '-' These are equivalent to <%= %> and <% %> respectively in erb.
What you want would look like this:
%p
results found for
%strong= #query
Which would produce the html:
<p>results found for <strong>#query</strong></p>
It should be noted that the '=' to start Ruby evaluation can only come at the beginning of the line or after a tag declaration and that only one tag declaration can occur per line.
The Ruby Evaluation section of the reference you linked covers embedded Ruby in detail and the haml tutorial which covers embedded ruby and many other haml basics is here:
http://haml-lang.com/tutorial.html
Here's how I'd do it:
%p No results found for <strong>#{h #query}</strong>
I'm not sure, but you might need a non-breaking space to preserve the space between the for and the <strong>
%p results found for
%strong= #query

Resources