2011-01-20 5 views
2

私はfoobarの2種類があり、fooは多くがbarsです。ActiveRecord保持スコープカプセル化

Barは、特定の期間発生するイベントです。そのため、現在アクティブなバーを持つフォームを表すActiveRecord::Relationを返すメソッドまたはスコープが必要です。

これは、スコープと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) 

foobarの内部に関する非常に多くを知っている必要があるということです。

にスコープを追加することでこれを書き換えることができるので、foobarの属性を知る必要はありませんか?

答えて

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

これは私が持っているものとは少し異なります。私の場合は、現在のバーを持つフォースが返されます。あなたが言及しているように、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という2つのクエリオブジェクトを作成し、このオブジェクトを共同作業させて、各クエリオブジェクトが対応するモデルに関連するロジックをカプセル化するようにすることができます。

関連する問題