Find methods in controllers

Posted on April 19, 2007

Recently, I’ve vowed to remove most of the model.find methods from my controller. I am not talking about simple find statements like:


 model.find(1) 
 model.find_by_title("my title") 

I am talking about find methods like so:


  model.find(:all, :conditions => ["status = ?", my_status])
  model.find(:all, :conditions => ["title = ?", my_title])

I would add methods on the model called, find_all_by_status(status) and find_all_by_title(title). Now, you may be thinking that these are simple find statements too. And I would agree with you. But in my opinion it makes the controller code look dirty. What would you rather see in your controller?


  model.find(:all, :conditions => ["status = ?", my_status])

~OR~

  model.find_all_by_status(my_status)

Which one can you comprehend faster? For me, the first statement takes some time for my brain to process, where as the second statement doesn’t not. Ok, if this isn’t enough to convince you. What if you introduce a new boolean attribute on your model called ‘active’ and the logic is to only show active model instances? Now you have to change all the places where you have:


  model.find(:all, :conditions => ["status = ?", my_status])

 ~TO~

  model.find(:all, :conditions => ["status = ? and active = ?", my_status, true])

You say you were thinking ahead and have a private method on your controller to handle this call, so you only have to make the change in one place. I would say congratulations, but I would point out that I think the controller knows too much about the model and thus breaks encapsulation.

I would like to hear what other think, and how they handle this situation.

Rspec'ing Model Associations

Posted on February 27, 2007

How do you go about spec’ing model associations?

There’s an idea on the rspec mailing list.

However, I kind of like using reflect_on_association. Let’s say we have the following model:

class Product < ActiveRecord::Base

  has_and_belongs_to_many :categories
  has_many :images
  has_many :inventories
  belongs_to :designer

end

Then my context and specifications might look like:

context "Product model" do

  specify "should respond to inventories" do
    Product.reflect_on_association(:inventories).should_not_be_nil
  end

  specify "should respond to categories" do
    Product.reflect_on_association(:categories).should_not_be_nil
  end

  specify "should respond to images" do
    Product.reflect_on_association(:images).should_not_be_nil
  end

  specify "should respond to designer" do
    Product.reflect_on_association(:designer).should_not_be_nil
  end
end

This will catch the situation where an association definition is removed or changed.