2011-01-20 3 views
2

У меня есть две модели, foo и bar, foo имеет много bars.ActiveRecord область хранения инкапсулированная

Bar - событие, которое происходит в течение заданного периода времени, поэтому мне нужен метод или область действия, которая возвращает ActiveRecord::Relation, представляющий foos, которые имеют активные бары.

Это достаточно просто в Foo классе с областью:

class Foo < ActiveRecord::Base 
has_many :bars 

scope :has_current_bars, joins(:bars).where('bar.foo_id IS NOT NULL').where('bar.starts_at <= ?', DateTime.now).where('bar.ends_at >= ?', DateTime.now) 

Что мне не нравится это, то, что foo нужно знать очень много о внутренностях bar.

Можно ли это переписать, возможно, добавив область на bar, так что foo не нужно знать об bar атрибутах?

ответ

1

Абсолютно. Вы можете и должны перенести область на Bar.

class Bar < ActiveRecord::Base 
    belongs_to :foo 

    scope :current, where('starts_at <= ? AND ends_at >= ?', DateTime.now, DateTime.now) 
end 

foo = Foo.first 
foo.bars.current # Will return all of foo's bars which match the scope 

# EDIT: 
bars.current.map(&:foo) # Will return all foos that have current bars 
+0

На самом деле, я думаю, вы могли бы перепутать их. – DanneManne

+0

@ DanneManne Вы правы, я прочитал его назад. Ред. – vonconrad

+0

Это немного отличается от того, что у меня есть. Mine возвращает foos с текущими барами. Ваш, как вы говорите, возвращает текущие бары, учитывая foo – SooDesuNe

0
class Foo < ActiveRecord::Base 
    has_many :bars 

    def self.has_current_bars 
    joins(:bars).merge(Bar.current) 
    end 

    # or 
    scope :has_current_bars, joins(:bars).merge(Bar.current) 
end 

class Bar < ActiveRecord::Base 
    scope :current, where('bar.starts_at <= ?', DateTime.now).where('bar.ends_at >= ?', DateTime.now) 
end 

foos = Foo.has_current_bars 
0

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

https://github.com/ElMassimo/queryable

Он заботится о ваших решениях прицелов в цепочку, и делегируя методы, как каждый и карту фактического запроса.

Для этого случая у вас могут быть два объекта запроса, FooQuery и BarQuery, и чтобы эти объекты взаимодействовали, чтобы каждый объект запроса выполнял инкапсуляцию логики, относящейся к соответствующей модели.

 Смежные вопросы

  • Нет связанных вопросов^_^