Ruby & Rails: Variable in string - ruby-on-rails

This is my code and it is loaded in a helper-class
output += '<button class="del_account" param-del="{account.id}">delete</button>'
When I render this to html, account.id is just converted to a string. And not the 'id' that I need. How can I solve this? Because this isn't working either.
output += '<button class="del_account" param-del="#{account.id}">delete</button>'
or this
output += '<button class="del_account" param-del="' +account.id +'">delete</button>'
thanks for your help.

If you need to use both " and ' symbols then here is simple way to deal with them:
output += %[<button class="del_account" param-del="#{account.id}">delete</button>]
This way you can safely place any of mentioned symbols without worrying to escape them.

You could use the Rails helper method content_tag (documentation) which makes things a bit cleaner and more readable.
output += content_tag(:button, "delete", :class => "del_account", :'param-del' => account.id)
Also, technically 'param-del' makes your HTML invalid - your custom attributes should begin with 'data-', so updating above would become:
output += content_tag(:button, "delete", :class => "del_account", :'data-account-id' => account.id)

Related

Ruby - link_to - How to add data directly from DB

First of all, I am very new to ruby and I am trying to maintain an application already running in production.
I have been so far able to "interpret" the code well, but there is one thing I am stuck at.
I have a haml.html file where I am trying to display links from DB.
Imagine a DB structure like below
link_name - Home
URL - /home.html
class - clear
id - homeId
I display a link on the page as below
< a href="/home.html" class="clear" id="home" > Home </a>
To do this I use 'link_to' where I am adding code as follows
-link_to model.link_name , model.url, {:class => model.class ...... }
Now I have a new requirement where we have a free text in DB, something like -
data-help="home-help" data-redirect="home-redirect" which needs to come into the options.
So code in haml needs to directly display content versus assign it to a variable to display.
In other words I am able to do
attr= '"data-help="home-help" data-redirect="home-redirect"' inside the <a>, but not able to do
data-help="home-help" data-redirect="home-redirect" in <a> tag.
Any help would be greatly appreciated!
link_to accepts a hash :data => { :foo => "bar" } of key/val pairs that it will build into data- attributes on the anchor tag. The above will create an attr as follows data-foo="bar"
So you could write a method on the model to grab self.data_fields (or whatever it's called) and split it into attr pairs and then create a hash from that. Then you can just pass the hash directly to the :data param in link_to by :data => model.custom_data_fields_hash
This somewhat verbose method splits things out and returns a hash that'd contain: {"help"=>"home-help", "redirect"=>"home-redirect"}
def custom_data_fields_hash
# this would be replaced by self.your_models_attr
data_fields = 'data-help="home-help" data-redirect="home-redirect"'
# split the full string by spaces into attr pairs
field_pairs = data_fields.split " "
results = {}
field_pairs.each do |field_pair|
# split the attr and value by the =
data_attr, data_value = field_pair.split "="
# remove the 'data-' substring because the link_to will add that in automatically for :data fields
data_attr.gsub! "data-", ""
# Strip the quotes, the helper will add those
data_value.gsub! '"', ""
# add the processed pair to the results
results[data_attr] = data_value
end
results
end
Running this in a Rails console gives:
2.1.2 :065 > helper.link_to "Some Link", "http://foo.com/", :data => custom_data_fields_hash
=> "<a data-help=\"home-help\" data-redirect=\"home-redirect\" href=\"http://foo.com/\">Some Link</a>"
Alternatively you could make it a helper and just pass in the model.data_attr instead
link_to "Some Link", "http://foo.com/", :data => custom_data_fields_hash(model.data_fields_attr)
Not sure you can directly embed an attribute string. You could try to decode the string in order to pass it to link_to:
- link_to model.link_name, model.url,
{
:class => model.class
}.merge(Hash[
str.scan(/([\w-]+)="([^"]*)"/)
])
)

How do you call a Rails helper in a HAML template

Right now I have some filler code in a mockup such as the following:
%img{:alt => "image description", :src => "img/img-11.jpg"}
Ideally though, I need to reference img-11.jpg from the asset pipeline as I do in my CSS:
<%= asset_path "img-11.jpg" %>
How does one rewrite the markup above to call asset_path within the context of a HAML template?
HAML is basically the same, but without the surrounding brackets if you're doing it inline:
= asset_path "img-11.jpg"
Otherwise you should be able to use it in the definition:
%img{:alt => "image description", :src => asset_path("img-11.jpg")}
In this case, use = image_tag('img-11.jpg', alt: 'Image Description'), but in the general case, use = function_name_or_ruby_code to evaluate any arbitrary Ruby and output the result.
You can use - ruby_code to evaluate Ruby without outputting the result.

Rails print whitespace from controller

I'd like to debug a variable #num in my Rails controller, so I'm evaluating
<%= #num %>
in my Rails view. However, I cannot distinguish between #num being '', ' ', and ' ' (and other different types of whitespace) when it's printed in the HTML. Is there any way to print it out clearly?
If you want to be really sure:
<%= #num.inspect %>
When #num = ' ' this should render:
" "
#inspect is great when you want to a representation of some object as a string.
If this is a complex object or large array or deep hash, I often prefer #to_yaml for inspection which lays it out in a somewhat readable format.
# controller
#foo = {:a => [:bar, :baz], :b => 123, :c => 'omg'}
# view
<pre><%= #foo.to_yaml %></pre>
# visible output
---
:b: 123
:c: omg
:a:
- :bar
- :baz
<%=debug #num %>
Will format it in haml.
<%= #num.inspect %>
Will format it as "p" does.
See Debugging Rails Applications (rails guides)

Rails Helpers with iterators

I have the following helper method:
def tile_for( photo, tileClass = nil )
div_for( photo, :class => tileClass ) do
link_to( image_tag( photo.image_url(:sixth) ), photo )
content_tag( :div, photo.location(:min), :class => 'caption' )
end
end
The problem is, it returns this kind of output:
<div id="photo_25" class="photo">
<div class="caption" style="display: none;">Berlin</div>
</div>
As you can see the link_to is not being output. I guess this is because only the returned value of the block is being included, rather than each executed line? I don't really understand why this kind of code works perfectly in views but doesn't work the same at all in helper methods. Can anyone enlighten me on what's going on and why it works the way it works? How would you build an loop helper method like this?
It works in views since ERB is really just a big concatenation engine. You need to "manually" do this work in your helper, since the code will not be interpreted by ERB:
def tile_for( photo, tileClass = nil )
div_for( photo, :class => tileClass ) do
  link_to(image_tag( photo.image_url(:sixth)), photo)
+ # <- Add this so the block returns the whole string
    content_tag(:div, photo.location(:min), :class => 'caption')
  end
end
div_for also supports arrays, which will be collected into one continuous string. So you can also do like so:
[link_to(image_tag(photo.image_url(:sixth)), photo),
content_tag(:div, photo.location(:min), :class => 'caption')]
Any of the other answers would do. Now, an explanation on why it does works in ERB.
In an ERB template, when a <%= is found, it gets translated to "#{#insert_cmd}((#{content}).to_s)". A simple example: <%= "a" %> gets translated to print "a".
You can take a look at line 631 in erb.rb but skim the previous code for a shake of context (related to the content).
Only the last value of a block is returned. You'll need to make sure your block returns a single value:
def tile_for( photo, tileClass = nil )
div_for( photo, :class => tileClass ) do
link_to( image_tag( photo.image_url(:sixth) ), photo ) +
content_tag( :div, photo.location(:min), :class => 'caption' )
end
end

Rails / Ruby - HTML attribute problem -

I have a tooltip that use this html attribute "original-title".
I have tryed this:
content_tag(:span, '', :class => options[:pinfo_class], :original-title => options[:pinfo])
But it gives a error in view.
Then I have used this which works, but not with the tooltip.
content_tag(:span, '', :class => options[:pinfo_class], :original_title => options[:pinfo])
How do I force rails to use the :original-title ?
You can use a string as a hash key, like 'original-title' => options[:pinfo]. Should work.
Also, most strings can be converted to symbols via 'some-string'.to_sym method, or even defined as :'some-string'.

Resources