Jake Scruggs

writes ruby/wears crazy shirts

So I had this form in a Rails view that needed some changes so, amongst other things, I changed this:
form_tag(:action => 'search')

to this:
form_tag(:action => 'show', :method => :get)

I had noticed that the show and search methods essentially did the same thing (and had the same views) -- which I why I refactored. However, when I made the change I got a 500. I was using restful routes and this form needed to be a get -- which I thought I had indicated. But I had not -- what should have put in the view was this:

form_tag({:action => 'show'}, {:method => :get})

There's this idiom in Ruby where we don't put curly braces around hashes if we don't need to, but I've consistently lost a bunch of time to mistakes like the one above. So I'm thinking about explicitly denoting hashes with curly braces in my future Ruby code just to improve intentionality.


Micah said...

This one has bitten me before as well. I'd agree that using braces in this case would clarify the code. I also think the API would nicer if it accepted just one hash and sorted out the elements itself.

pragmatig said...

wrong solution to a valid problem imo

There is no obvious difference between changing :x=>1 to :x=>1 :y=>2 and {:x=>1} to {:x=>1,:y=>2}

The only problem-solving method would be to use {:x=>1},{} for every call, but who wants to do this...

Anonymous said...

Yeah, taking 2 hashes as params is just plain bad ruby api design. Dealing with it for so long that I'm used to it, but I hope that doesnt stop the core team from fixing form_tag to work with :url and :html parameters like all the other form helpers.

Jared said...

It's a Ruby-ism for the interpreter to gather all the trailing arguments as a hash, even without the curlies. The reason you were seeing the 500 errors is because form_tag will actually take two hashes as arguments, a url_for hash, and an HTML options hash.

You could actually write you code to look like:

form_tag({:action => :create}, :method => :post)

And it would still be valid.