views:

22

answers:

1

I'd like to extract out logic from the controllers to somewhere that it can be more DRY. What's the best way of handling something like the following in Rails?

For instance, as opposed to having the query in the controllers, I could place it in the model:

class SmoothieBlender < ActiveRecord::Base
   belongs_to :user

   def self.get_blenders_for_user(user)
      self.where(["user_id = ?", user.id])
   end
end

Or would it be better to create a module as a service layer and include that in each model that uses it?

module BlenderUser
   def get_blenders_for_user(user)
      SmoothieBlender.where(["user_id = ?", user.id])
   end
end

class SmoothieBlender < ActiveRecord::Base
   include BlenderUser
   belongs_to :user
end

class User < ActiveRecord::Base
   include BlenderUser
   has_many :smoothie_blenders
end

Or just make it a full blown service class that's accessible from the User and Blender controller? Where would you put this class?

class BlenderService 
    def self.get_blenders_for_user(user)
       SmoothieBlender.where(["user_id = ?", user.id])
    end
end

I'm new to Ruby and Rails, so if this is a silly question/syntax is incorrect, forgive me. Thanks in advance!

+2  A: 

I'd create a named_scope (I think it's just scope in Rails 3)

class SmoothieBlender < ActiveRecord::Base
   belongs_to :user

   scope :for_user, lambda { |user_id|
      where("user_id = ?", user_id)
   }  
end

This way you can call

SmoothieBlender.for_user(user.id)
j.
Ahh, makes sense! Kind of like Extensions in .Net. Thanks!
MunkiPhD
If the parameter is coming in from a form in params, remember to use .to_i on it. Eg where("user_id = ?", user_id.to_i)
Larry K
to_i will try to parse it and fail if it's not sanitized I presume?
MunkiPhD