2

我有两个模型,foo并且barfoo有很多bars

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属性?

4

3 回答 3

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
于 2011-01-20T03:07:39.587 回答
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
于 2013-08-28T01:23:05.593 回答
0

如果你想封装你的查询对象,我编写了一个微型库,它可以非常简单地将复杂的查询逻辑移到你的模型和控制器之外。

https://github.com/ElMassimo/queryable

它负责使您的范围可链接,并委托方法如 each 并映射到实际查询。

对于这种情况,您可以有两个查询对象,FooQuery 和 BarQuery,并使这些对象协作,以便每个查询对象负责封装与其相应模型相关的逻辑。

于 2014-04-13T18:25:38.873 回答