How to upgrade Ruby on Rails Restful routes to 2.0
Ok, you were quite proud when on Rails 1.2.x you made your app restful.
Now in 2.0 REST has been improved cleaned reworked and... changed the naming of the nested Routes
Let's take a look at the differences in 1.2.x
the following code
map.resources :dinners do |dinner|
dinner.resources :dishes do |dish|
dish.resources :side_courses
end
dinner.resources :drinks
end
would generate (among many others)
dinners_url
dinner_url
dishes_url
dish_url
side_courses_url
side_course_url
drinks_url
drink_url
and so on.
With the same code in the routes rails 2.0 generates
dinners_url
dinner_url
dinner_dishes_url
dinner_dish_url
dinner_dish_side_courses_url
dinner_dish_side_course_url
dinner_drinks_url
dinner_drink_url
And your REST routes methods will change more if you use the new routes namespacing introduced with 2.0
This is good and much nicer, and is a great help in complicated applications that use the same resources at different nesting levels and for different purposes.
But it means that to migrate from 1.2.x you've got to change many of your original calls to the *_url or *_path methods.
Well, I wrote a small dodgy script to manage the search and replace of the old routes with the new ones.
And I thought I'd share it...
The script should run as it is on linux. It uses find/grep/sed system commands.
first two steps are quite simple
- upgrade a non critical copy of your rails app to version 2.0 of ruby on rails
- download the script to migrate your routes from 1.2 to 2.0 and save it in the root directory of your rails project
- execute script/console and type the following
require 'route_migrator'
RouteMigrator.dump_current_route_methods - exit from the console and open with a text editor the file route_map_2_0.rb. This file should contain a ruby hash with keys and values containing the old routes
- now you have to update the values of the hash with the new routes, for the previous example a line would look like
"side_courses_url" => "side_courses_url"
and you need to update it to
"side_courses_url" => "dinner_dish_side_courses_url"
If you don't have a clear idea about what the new routes are you can use
rake routes
or open again script/console and type
require 'route_migrator'
RouteMigrator.dump_named_routes
Be aware of that the hash might contain some rubbish as keys, just delete the lines that you think aren't proper routes actually used in your applications, - When you think your hash is complete and ready to go you can check your work firing yet another time your script/console and typing
require 'route_migrator'
RouteMigrator.check_new_routes
This will output a warning if you've typed in the hash some routes that are not in the list generated from 2.0 - If the previous check succeeded you can try the following that will substitute every occurrence odf your old routes with the new ones
WARNING: this script is guaranteed to screw up >>BADLY<< your code if you use it without understanding what it does. Read the source code of the script before proceeding. As always svn diff and svn revert will be your friends
require 'route_migrator'
RouteMigrator.upgrade_route_methods!
At this point your application should be updated with the new routes
6 comments:
Hey Paolo, nice article,
you're missing and end in the first code block
Thanks macournoyer I think it should be fixed now.
I gave this a shot but when I ran the code at step 3 it wrote a file on my machine named route_coll.txt and it grew really fast. After it reached about 1.6gb I killed the process and removed the file. Thoughts?
@glennford
I'm pretty sure the script is trying to parse the log of your app or you have some symbolic links in place that create a sort of loop in your application code.
I've modified the script to make it analyze only the "app" dir.
Let me know if is any better.
That did the trick! Instead of doing step 5 I altered the code to call "check_new_routes" on the keys created with "dump_current_route_methods". This was a quicky on line 22 with:
"#{m}" => ""
becoming
"#{m}" => "#{m}"
In doing so, rather than searching all 50+ of my routes for their correct counterparts manually, it simply told me I had 3 non-existing routes. Very helpful! I'm tracking them down now and fixing them. Thanks so much for your helpful code!
@glennford
thanks a lot, I've included your change in the script!!
Post a Comment