Rails's url_for weaknesses
Rails helper link_to
is the most famous and used any Rails developer. Usually the first argument is a link name and the second is a parameters which are used to build url. You are able to pass 4 types of these parameters: helper which is generated by routes, string, hash and since rails 3 - record. But when and which one to use for your task? This is an interesting question.
url_for
Passed to link_to
parameters go to the url_for
method. This method builds known url which is eventually passed to the href
attribute of generated link. So to answer on this question we should answer on question what and when to pass to the url_for
.
As I’ve already said url_for
accepts 4 types of parameters and see how it’s possible to pass them there:
All there calls of url_for
generate the same result /events/:id
, for example /events/1
.
The most convenient seems the last call - you just pass @event
record and that’s it. There is no any brainstorming or surfing generated routes with rake routes
task (this task shows all available routes for your Rails application, run it if you still hadn’t done this yet). It really convenient not only that’s why but it will be useful when you change controller or route which serves the event. You won’t have to change all your entire code in Rails application where you used old route helpers or string urls, hashes and so on.
The most complicated seems the hash variant. It looks the biggest and there is no doubt that why it is silently deprecated by Rails community. Rails developers avoid to using it at all. The reason is not only in this reason but in one more which I will tell you in a few seconds.
There is no any rule which method of proposed to use and of course you are not restricted to use any of these call types.
But let’s see what is their speed. I wrote the benchmarking test especially for this case:
And these are results of their running:
rake test test/helpers/events_helper_test.rb
Run options: --seed 23668
# Running tests:
Rehearsal -----------------------------------------------
string 0.010000 0.000000 0.010000 ( 0.019028)
helper 0.480000 0.010000 0.490000 ( 0.498942)
hash 1.250000 0.000000 1.250000 ( 1.253836)
polymorphic 0.920000 0.010000 0.930000 ( 0.924670)
-------------------------------------- total: 2.680000sec
user system total real
string 0.010000 0.000000 0.010000 ( 0.013747)
helper 0.480000 0.000000 0.480000 ( 0.478646)
hash 1.200000 0.000000 1.200000 ( 1.200571)
polymorphic 0.890000 0.000000 0.890000 ( 0.892464)
.
Finished tests in 5.542858s, 0.1804 tests/s, 0.0000 assertions/s.
1 tests, 0 assertions, 0 failures, 0 errors, 0 skips
As you see the slowest here is a hash style. And then polymorphic generating goes. Helper style on the 3rd place and it’s not surprise that string generating wins.
Conclusion
For my opinion the most convenient style here is polymorphic. But it’s 2x slower than helper style. String style is the fastest but we can’t use it because if you change your routes your tests may not show you that there is an error in generating routes - string will be generated as before but helper method won’t be presented and page will fail that’s why.
So my conclusion is to use helper methods everywhere where it’s possible. If you have some place in your application where you have to define which helper to use by record type or any other sign the polymorphic way is more preferable.
And the last conclusion - avoid using hash types of generating url at all.