簡體   English   中英

ActiveRecord保持范圍封裝

[英]ActiveRecord keeping scope encapsulated

我有兩個模型, foobarfoo有很多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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM