Many Rails helpers use an idiomatic options hash as their last argument; Ruby automatically inserts extra method arguments into that hash. I often find myself wanting to conditionally insert an element, or to write a helper that provides the element. Two examples in pseudo-Ruby:
link_to "Example 1", "http://www.example.com", needs_confirmation? ? :confirm => "Are you sure?" : nil # syntax error; nil can't be a hash element
or
link_to "Example 2", "http://www.example.com", unique_link_id
# I don't want to return a hash; I want to return an element of a hash
def unique_link_id
:id => "our_link_#{user.id}" # Syntax error
{:id => "our_link_#{user.id}"} # valid, but returns a hash that ends up being an element of the options hash
{:id => "our_link_#{user.id}"}.flatten_into_my_parent_hash # What's in my brain
end
Is there some elegant way to do this? I can’t control the Rails helpers, obviously, so I can’t force them to flatten the hash. (Er, not that there’s a Hash#flatten method, but even if there were.)
I can build the hash as a variable before the method call, of course, and optionally add elements, but… ick.
Let’s stipulate that these are contrived examples, and assume that the helpers wouldn’t allow :confirm => nil or :id => nil, and that unique_link_id might want to leave off the ID. I’m more interested in the hash syntax than in solving a Rails problem.
Anyone?
I think you should try something like the following:
And for the second case you could in a similar say the following:
Note: unique_link_id should return a string (or nil if you dont want to have an id)
To answer your question in general you need to understand how rails treats these parameters that you pass in a method (such as a helper).
Most rails helpers start like this:
What you should know about the above: It is assumed that an Array is passed in as parameter. All of the :something=>value that you also add are converted into a hash which is the last element of this array. So
extract_options!separates the normal parameters from the hash options. So in order what you want to work, all options should be in one hash in the end.To make a long story sort here is an example of what you should do:
In this case
unique_link_idreturns a hash and is merged with the other options. Ifunique_link_idreturns an empty hash({}) nothing is added to your options and everyone is happy 🙂If your options get too complicated i suggest that you create an options variable before calling the helper (or method) you wish.
optionsshould be a hash merged with other hashes as many times as you wish before you pass it as the last parameter to your method.Tip: very useful hash functions are hash.merge(), hash.merge!() and hash.reverse_merge()