[英]ActiveRecord keeping scope encapsulated
我有兩個模型, foo
和bar
, foo
有很多bars
。
Bar
是在給定時間段內發生的事件,因此我想返回一個ActiveRecord::Relation
的方法或作用域,該ActiveRecord::Relation
表示具有當前活動bar的foo。
在具有范圍的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
是, foo
需要了解bar
的內部知識。
是否可以通過在bar
上添加作用域來重寫它,所以foo
不需要了解bar
屬性?
絕對。 您可以並且應該將范圍移到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
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
如果您想封裝查詢對象,我已經編寫了一個微型庫,可以輕松地將復雜的查詢邏輯移出模型和控制器之外。
https://github.com/ElMassimo/queryable
它負責使您的范圍可鏈接,並委派每個方法和映射到實際查詢的方法。
對於這種情況,您可以有兩個查詢對象FooQuery和BarQuery,並使這些對象協作,以便每個查詢對象負責封裝與其對應模型有關的邏輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.