Today I’m starting on upgrading my Rails 2 project to Rails 3 and I thought I’d put all the changes I need to make to get it working here incase anyone runs in to the same problem(s).
Prepping for this shit
I made sure I had the following tools before I started (this step is VERY important):
- Enough Coffee
- Get EVERYONE out of the house (Make sure your girlfriend or wife isn’t around. Porting Rails 2 to 3 may in some cases be bad for your relation ship due to shouting, cursing and/or throwing stuff at her)
- Headphones
- Good music — I prefer the following: DI.fm dubstep
- Porn (If that’s what keeps you calm! Hey I’m not saying I’m watching it .. but, you know, if that’s your thing go for it!)
My gems:
Before I started I checked my environment for gems and made sure they were working with rails 3 and moved them over to the new rails project in to the Gemfile. The project uses the following Gems (=> Replaced with):
- pluginaweek-state_machine
- validation_reflection => removed
- authlogic => devise
- searchlogic => meta_search
- compass => more/less
- haml => removed
- formtastic
- will_paginate
- inherited_resources
- responders
- has_scope
- hpricot => nokogiri
- gruff => removed
- rboss
- exception_notifier
Errors Problems (notes)
The problems I’ve run in to are none so far:
SASS to Less
This is an absolute pain, I swear. I haven’t been able to find a tool which can convert SASS to Less so I have to do everything by hand (If at this point you’re thinking, DUDE, you stupid fuck use XXXX for that or use XXX regexp for that. Then please do share!). I did came up with this Regexp which should make it a little bit easier if you’re using TextMate (or any other editor):
Find:
/^(\s*):?(\S*)([\s\S*]*)/i
And replace:
$1$2:$3;
All you have to do by hand is add de brackets around your classes and IDs
Active Record — Custom select
I have the following scope with a custom select:
scope :include_matches_count, lambda { select("organizations.*, SUM(spider_webs.matches_found) AS spider_matches_found"). joins("LEFT JOIN orders ON organizations.id = orders.organization_id LEFT JOIN spider_webs on orders.id = spider_webs.webs_id AND spider_webs.webs_type = 'Order'"). where('(spider_webs.id = (SELECT id FROM spider_webs AS n WHERE n.webs_id = orders.id AND n.webs_type = "Order" ORDER BY n.id DESC LIMIT 1) OR 1 = 1) AND organizations.customer_id = ?', User.current.customer_id). group('organizations.id') }
If you would call this scope (say my model is called `MyObject`) MyObject.include_matches_count.empty? You’ll get the following error:
undefined method `zero?' for #
Hmm now that’s odd. Up on close inspection I noticed I had a very strange select in my console output:
SELECT COUNT(*) AS count_all, organizations.id AS organizations_id FROM `organizations` LEFT JOIN orders ON organizations.id = orders.organization_id LEFT JOIN spider_webs on orders.id = spider_webs.webs_id AND spider_webs.webs_type = 'Order' WHERE ((spider_webs.id = (SELECT id FROM spider_webs AS n WHERE n.webs_id = orders.id AND n.webs_type = "Order" ORDER BY n.id DESC LIMIT 1) OR 1 = 1) AND organizations.customer_id = 3) GROUP BY organizations.id
Huh? Where did my custom select go to? So I checked the rails code and it seems that if the object hasn’t been loaded before .empty? is called, Rails decides to just call count.zero? on the object. Ignoring your select and causing this error.
So if you have a custom select in a scope and you would like to check if the result is empty before displaying it make sure you call “.all” on it first:
MyObject.the_scope_with_a_custom_select.all.empty?
updating while I’m on the train.