Intermediate Rails Tips

I’ve been working a lot with Rails over the last several months and can say that I’ve learned quite a bit. Some things I still curse, but for the most part Rails makes development pretty painless. I’m logging some lessons here for myself; maybe you’ll find them useful as well.



Tip 1: Use Rails caching (page, action, and fragment)

Rails has built in caching mechanisms in the form of page caching, action caching, and fragment caching.


I almost aways start by caching any static pages in my site controller. Note: page caching requires write access to the filsystem. if you’re hosting on Heroku, you won’t be able to use this. Use action caching, backed by memcached, instead.


Use fragment caching around common DB queries; pay special attention to those that necessitate a .all query. Tags, categories, and other infrequently changing data are good candidates.


Note that once you start caching, you’ll probably need start managing your cache as well, expiring pages, actions, or fragments after updates to your models. See observers below.



Tip 2: Consolidate your migrations

Migrations are one piece of rails with which I have a love/hate relationship, particularly with ActiveRecord. One the one hand it’s convenient to have a versioned snapshot of all schema changes. On the hand, early in development, they become a big burden.


Defining new fields using migrations or even creating new migrations by hand becomes absolutely maddening early in development. I’ve opened Rails projects with 50+ migrations. Do yourself a favor, and DON’T create a new migration for every little schema change. Define all your base fields in a respective migration and blowout your database (drop && create) - user fields in a create_users.rb, category fields in a create_categories.rb, etc.


This doesn’t exactly rid you of migration woes unfortunately. It means your entire team will need to be aware of the way you’re developing AND you still incur the cost of the rake db:drop && rake db:create && rake db:migrate every time you make a change to one of your migrations. I created a special rake task to do this setup for me.


task :dev_setup => :environment do
  puts "SETTING DB UP FOR DEV..."
  if(`ps -ef` =~ /script\/rails c/)
    puts "Please exit rails console and rerun!"
    exit
  end

  Rake::Task["db:drop"].invoke
  Rake::Task["db:create"].invoke
  Rake::Task["db:migrate"].invoke
  Rake::Task["db:seed"].invoke
end



Tip 3: Use ActiveRecord Observers

Keep your callbacks in observers to avoid cluttering your models. I prefer managing my callbacks in observers, rather than attempting to organize them in my models. Register your observers in application.rb like so:

config.active_record.observers = :conference_observer, :transaction_observer



Tip 4: Don’t feel constrained by the Rails ViewHelpers

Rails encourages liberal use of their view helpers to the degree that sometimes I think the ideal Rails app would contain no markup at all. Personally, I’ve never been a huge fan of most of the helpers. That’s not to say they aren’t helpful, but don’t be afraid to fallback to writing vanilla markup in a jam. I’ve spent many hours crawling the web for a particular form_tag helper example because of an undocumented quirk. It it sometimes easier just to write it by hand.


I know there are plenty of other strategies and tips. Feel free to chime in.