Learn to love your models

Posted on March 06, 2007

When I firsted started writing Rails Apps, coming from the Java world, I forgot all my good OOP training. Within Rails, I viewed the model as this magically class that gave me all this power and I was afraid to add any of my own behaviour to the model. Which went against my previous way of doing things, which was to place as much of the business functionality within the model.

Well, I am glad Jamis came along and wrote this post.

I am back on track. I don’t know how many times I wrote something like this in a controller:

   def update
       @user = User.find(params[:id])
       @subscription_plan = SubscriptionPlan.find(params[:plan_id])
       @subscription_plan.update_attribute(:status, 'active')

       # deactivate previous plans
       @user.subscription_plans.each {|plan| plan.update_attribute(:status, 'disabled') if plan.status == 'active'}
       @user.subscription_plans << @subscription_plan
   end

This is just ugly. And goes against a lot of OOP best practices. The controller knows too much about the internals of the User and Subscription Plan models. Also, if I wanted to test this controller action using mocks and stubs, I would have to write a bunch of code. What if I fixed the controller code to be like so:

   def update
     @user = User.find(params[:id])
     @subscription_plan = SubscriptionPlan.find(params[:plan_id])
     @user.upgrade_to_subscription_plan(@subscription_plan)
   end

This is much cleaner and easier to mock/stub. Also, if I decided to change the behavior of how a user upgrades their plan, the upgrade_to_subscription_plan method isolates any changes from the controller action – as long as the method signature doesn’t change.

So, go ahead a love your models.