Лучшая практика для абстрагирования запросов модели ActiveRecord в Rails?

Я хотел бы извлечь логику из контроллеров куда-нибудь, чтобы она была более СУХОЙ. Каков наилучший способ обработки чего-то вроде следующего в Rails?

Например, вместо того, чтобы иметь запрос в контроллерах, я мог бы поместить его в модель:

class SmoothieBlender < ActiveRecord::Base
   belongs_to :user

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

Или было бы лучше создать модуль как сервисный уровень и включить его в каждую модель, которая его использует?

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

Или просто сделать его полноценным сервисным классом, доступным из контроллера User и Blender? Где бы вы разместили этот класс?

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

Я новичок в Ruby и Rails, поэтому, если это глупый вопрос/неверный синтаксис, простите меня. Заранее спасибо!


person MunkiPhD    schedule 26.08.2010    source источник


Ответы (1)


Я бы создал named_scope (думаю, это просто scope в Rails 3)

class SmoothieBlender < ActiveRecord::Base
   belongs_to :user

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

Таким образом, вы можете позвонить

SmoothieBlender.for_user(user.id)
person Ju Nogueira    schedule 26.08.2010
comment
Ааа, логично! Что-то вроде расширений в .Net. Спасибо! - person MunkiPhD; 26.08.2010
comment
Если параметр поступает из формы в params, не забудьте использовать для него .to_i. Например, где (user_id = ?, user_id.to_i) - person Larry K; 27.08.2010
comment
to_i попытается разобрать его и потерпит неудачу, если он не продезинфицирован, как я полагаю? - person MunkiPhD; 29.08.2010