set data-* attribute - ruby-on-rails

I have a situation where I need to set dinamically the value for "data-*" on a div. The code I'm using actually is this one:
= tag('div', { class: 'agile-carousel',\
data: { carousel_list: url_for(format: :json) } }, true)
= "</div>".html_safe
Which is horrible. Also rails closes the div in a <div /> fashion, which chrome and other browsers definitely don't like (creating some disasters).
So my solution is that one. I would like to ask if there is another way to do this.
Update 1:
Small issue I have, this code:
span class==I18n.locale == locale_used ? "inactive" : nil
= link_to(I18n.t('locale_name', locale: locale_used),\
url_for(locale: locale_used))
If I remove link_to it works. Notice that if I insert even something like | text it returns an error: syntax error, unexpected keyword_ensure, expecting $end

You can use content_tag instead of tag to produce a <div></div> instead of a <div>, but you shouldn't.
You're using Slim, so use Slim:
.agile-carouesel data-carousel_list=url_for(format: :json)
Output:
<div class="agile-carouesel" data-carousel_list="some URL"></div>
The whole point of Slim and HAML is that you have this fantastically terse syntax for writing tags. You should use it, rather than resorting to Rails' tag helpers when they're not needed. By using them, you're reintroducing all the punctuation clutter that they're supposed to remove.

Related

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

Haml::SyntaxError: Invalid attribute list

I am trying to interpolate a ruby variable in a HAML%img src tag, with the ruby interpolation operator #{}. In the following way:
-#locations.each do |location|
%li
%img(src: "#{location.thumbnail_url}")
However, I get the following error:
Invalid attribute list: "(src: \"\#{location.thumbnail_url}\")".
Is there a valid way to do this? I am sure it has been done before but can't see any literature/any other posts about it.
It looks like you’re mixing the two attribute styles, the normal style and the HTML style.
You want to either replace () with {} and use the normal style:
%img{src: "#{location.thumbnail_url}"}
or use the HTML style with = instead of :, like this:
%img(src = "#{location.thumbnail_url}")

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).

Removing whitespace in a block in Haml

I have this:
= link_to user_path(f.object.user) do
%span.hourly-rate>= f.object.user.hourly_rate.to_currency
\/hour
Which renders as:
<a href="/users/44"><span class='hourly-rate'>$16</span>/hour
</a>
The close tag is on a separate line. This results in the link looking funny when there is underlining (eg. on hover)
The solution is to have the markup look like:
<span class='hourly-rate'>$16</span>/hour
But I haven't found a way of doing that in Haml. I'd prefer to keep using the block form of link_to if possible (I imagine not using the block would result in even messier code, but at this point I'm open to anything).
Tangent: I imagine this would be fixed if I was using the :ugly Haml option. I have Haml::Template.options[:ugly] = true in my config/environments/development.rb, and I have haml-rails in my Gemfile (I know it doesn't include :ugly, but it's worth mentioning), and I have an initializer with;
# config/initializers/haml.rb
Haml::Template.options[:format] = :html5
Haml::Template.options[:ugly] = true
... but the code still isn't ugly :( Any ideas why not?
If you can live with the content wrapped inside another div, you can use this:
= link_to user_path(f.object.user) do
%div<>
%span.hourly-rate>= f.object.user.hourly_rate.to_currency
\/hour
The span was being used by javascript, to get its value (in this case, the user's hourly rate) - it wasn't being used for CSS at all.
Thus, I ended up removing the span and adding the user's hourly rate as a data- attribute of a separate field. So the final markup for the link was
= link_to f.object.user.hourly_rate.to_currency + "/hour", user_path(f.object.user)

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