Wednesday, December 10, 2008

Ruby on Rails 10 Tips - Part 1: Development


I was recently asked by some colleagues for advices and best practices developing, securing, and deploying Ruby on Rails applications. While I don't have full fledge best practices, I do have lots of tips to share. These are not as thorough as best practices or well structured as patterns, but are instead short, to the point, common knowledge and not so common knowledge that I found useful in my experience developing Rails applications.

Also, most of these tips come from my either my own experience, discussion with others in the community at Meetup and RailsConf, as well as reading various blogs and books on the subject. I apologize in advance if I have not linked to your blog where you have similar tips. Feel free to leave a comment and I will do so.

Finally, I love a great debate. If you disagree with any of these tips then by all means post a comment and let me know what you disagree with and why. I know at least one colleague at IBM Research, Chet Murthy, who is experienced in Rails development and disagrees with me on at least one of these tips. I welcome your feedback Chet.

Enjoy!

10 Rails Development tips

  1. Use ActiveResource and avoid ActiveWebService. With ActiveResource and multiview support in Rails 2.x you can easily expose RESTful models as well as Atom/RSS feeds on these models as well as JSON and any other view format you can wish for.


  2. Consuming ActiveResource is easy by using self.site = "URL" in the client side. However, that does not add data to the DB and every query will result in a REST call. Caching data is key.


  3. Use Rake to automate any other tasks you do. Custom Rake tasks are easily added in lib/tasks. Use $rake -T to see current tasks available, including yours.


  4. Use database migrations to update models once your design is solid and you have a first release and cannot avoid data losses. That is, to be clear, use one migration per model early on and then once app is released for beta, every change to the models should be via new migration (not an update to the old migration). This will save lots of headaches in future and allow you to easily move application from one version to next one.


  5. Use Solr vs. Ferret for models searchability and associated acts_as_xyz plugins. This is due to the fact that Ferret indexes tend to get corrupted. This, in some sense, is a shame since Ferret is a nice and easy plugin.


  6. Make sure to use Rails validations in your models. I would avoid special DB statements in migration code. This makes it easier to move to different DB, e.g., MySQL to DB2.


  7. Use view partials to keep your views DRY. Essentially, partials should be any view code that is repeated, similar to a subroutine call (PullUp or PushDown method refactoring). Use a app/views/shared directory for partials that are across controllers. Also, always use the controller (or shared) name when calling the partial. This will help you avoid view errors when refactoring views into shared.

    So instead of:



    do instead


    When not specified the controller is assumed to be the one from the calling view. If you reused funky_partial in a view coming from a controller other than my_controller, you will get a view partial file not found exception. Easily fixed but easily avoidable as well.


  8. Don't add new actions to ActiveResource models, other than the basic CRUD operations' actions. Instead use a separate controller that groups actions related to one or many ActiveResources, e.g., don't add login/logout action in User model if that's an ActiveResource, and so on. This is because you will need to add special routing maps in your config/routes.rb and that will be hard to maintain. ActiveResouces are RESTful by design and the actions added with scaffold are good enough. Use $rake routes to see all your routes (more on this point later).


  9. Refactor common code as plugins after you notice it being used many places and applications. This is especially true for moving common model code into acts_as_xyz. This is harder to do when you first start but becomes easier after a few apps and you have done one. See this RailsOnWave tutorial for a intro guide to creating your own acts_as_xyz plugins


  10. Tests, test, test. Whether you test first or test last or in between, in many ways what matters is the fact that you are testing. Doing TDD means having some sustained development flow that always include tests. If your code base is growing one sided (that is tests are not growing in same rate as code) then something is wrong and you will pay for it in the future. Use $rake stats to get a feel for your current code/test levels.


Next I'll list my top 10 list of tips for Rails application deployments and scaling.