Adam Templeton
Adam Templeton

Reputation: 4617

Rails: Setting class and data-tag of an HTML attribute with a single rails method

I'm currently working on a tour interface that guides new users around my site. I have a Tour model that has many TourStops, each of which contains information about a section of the site.

Basically, I'd like to write a function for the Tour model that -- when passed the number of a TourStop -- generates the correct class and data attribute for the HTML element it's attatched to. For example, I'd like

<%= link_to image_tag("new_button.png", tour.stop_data(1), :title => 'Add new asset'), new_asset_path %>

to call a function and return something like

def stop_data(order)
     " :class => '#{tour_stops.find_by_order(order).name}', 
       :data => '{:order => order}'"
end

creating a link_to tag like:

<%= link_to image_tag("new_button.png", :class => 'tour_stop_1', 
       :data => {:order => 1}, :title => 'Add new asset'), new_asset_path %>

The above code doesn't work. Is something like this even possible? If not, what's a better approach I might take?

Upvotes: 0

Views: 981

Answers (1)

doesterr
doesterr

Reputation: 3965

The image_tag accepts two parameters. A source, and a options Hash.

What you are trying to do is squeezing your return value from stop_data into this options Hash.

In order to get this to work, you first, need to return a Hash from stop_data, and second, make sure you pass only two arguments to image_tag - the source, and the options.

First:

def stop_data(order)
  { 
    :class => tour_stops.find_by_order(order).name, 
    :data  => { :order => order } # you may need order.to_json
  }
end

Second:

link_to image_tag("new_button.png", tour.stop_data(1), :title => "Add new asset"), new_asset_path

This looks like it will work, but it won't, since your'e passing three parameters to image_tag.

When you do the following:

image_tag("new_button.png", :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset")

It looks like you're passing even 4 parameters to image_tag, but in fact they are only two. In Ruby, when the last parameter of a method is a Hash, you don't need to wrap the Hash key/value pairs in curly braces ({}), so the example above is essentially the same as

image_tag("new_button.png", { :class => "tour_stop_1", :data => { :order => 1 }, :title => "Add new asset" })

Now, to get your helper to work with image_tag, you need to merge the options, so they become only one Hash.

link_to image_tag("new_button.png", tour.stop_data(1).merge(:title => "Add new asset")), new_asset_path

Again, we're omitting the curly braces when calling merge, because it's only (and therefore last) parameter is a Hash. The outcome is the same as:

tour.stop_data(1).merge({ :title => "Add new asset" })

Upvotes: 2

Related Questions