如何根据Mongoid中的关系设置可链接范围

时间:2011-12-06 22:20:12

标签: ruby-on-rails scope mongoid

问题已修复...原来有一个活跃的记录方法已经过了写,现在一切都按预期工作

我正在尝试设置范围,以便我可以进行看似

的调用
Competitor.of_type(type).at_event(event)

将返回参加活动的所有类型的参赛者 我的模型看起来像

class Competitor < Competitor
  belongs_to :type
  has_and_belongs_to_many :events
  scope :at_event, ->(event) {where(:event_ids.in => event.competitor_ids)}
  scope :of_type, ->(type) where(:type_id => type.id)                
end

以下作品(返回mongoid标准)

Competitor.of_type(type)
Competitor.at_event(event)

但是当我将它们链接起来时,它会打印出如下所示的内容:

#<Competitor:0x00000109e2b210>
#<Competitor:0x00000109e2ab08>
-------=-=------------------------------------
=> #<Mongoid::Criteria
selector: {},
options:  {},
class:    Competitor,
embedded: false>

每个Competitor.of_type(类型)都有一个竞争者条目(第一个链接标准),如果我在查询上运行.count,我会得到数据库中竞争对手的总数。

在范围的mongoid文档的顶部,它表示所有范围都是可链接的,并且也可以应用于关联,后面将在关系部分中讨论。 不幸的是,我没有看到关系子部分,我不能在主要关系部分找到对范围的单一引用。

我能够得到以下内容以返回我想要的结果:

where(:id.in => event.competitor_ids).where(:type_id => type.id)

但是如果查询的任何部分被拆分为单独的方法或范围,它将失败并提供我在上面显示的结果。

2 个答案:

答案 0 :(得分:9)

范围

  

与Active Record类似,Mongoid允许您定义范围   模型作为过滤结果集的便利。范围已定义   在类级别,使用范围宏或通过定义类   返回条件对象的方法。所有示波器都是可链接的   也可以应用于关联,后面将讨论   关系部分。

命名范围是使用范围宏在类级别定义的,并且可以链接以在不错的DSL中创建结果集。

class Person
  include Mongoid::Document
  field :occupation, type: String
  field :age, type: Integer

  scope :rock_n_rolla, where(occupation: "Rockstar")
  scope :washed_up, where(:age.gt => 30)
  scope :over, ->(limit) { where(:age.gt => limit) }
end

# Find all the rockstars.
Person.rock_n_rolla

# Find all rockstars that should probably quit.
Person.washed_up.rock_n_rolla

# Find a criteria with Keith Richards in it.
Person.rock_n_rolla.over(60)
  

请注意,定义是在类加载时评估的。对于   在运行时进行评估,您需要确保使用a进行定义   proc或lambda。在以下示例中,第一个日期设置为   类加载的日期,第二个范围设置当时的日期   范围被称为。

scope :current, where(:start_date.lte => Date.today)
scope :current, -> { where(:start_date.lte => Date.today) }

类方法

对于那些喜欢Data Mapper样式语法的人来说,返回条件的类方法也可以被视为可链接的范围。

class Person
  include Mongoid::Document
  field :occupation, type: String
  field :age, type: Integer

  class << self

    def rock_n_rolla
      where(occupation: "Rockstar")
    end

    def washed_up
      where(:age.gt => 30)
    end

    def over(limit)
      where(:age.gt => limit)
    end
  end
end

# Find all the rockstars.
Person.rock_n_rolla

# Find all rockstars that should probably quit.
Person.washed_up.rock_n_rolla

# Find a criteria with Keith Richards in it.
Person.rock_n_rolla.over(60)

返回条件的命名范围和类方法可以链接在一起 - 这就是Mongoid强大的标准API之美。

class Person
  include Mongoid::Document
  field :occupation, type: String
  field :age, type: Integer

  scope :washed_up, where(:age.gt => 30)
  scope :over, ->(limit) { where(:age.gt => limit) }

  def self.rock_n_rolla
    where(occupation: "Rockstar")
  end
end

# Same queries apply here as well.
Person.rock_n_rolla
Person.washed_up.rock_n_rolla
Person.rock_n_rolla.over(60)

答案 1 :(得分:0)

尽管@MZaragoza的答案已完成,但似乎不再允许使用此语法:

scope :rock_n_rolla, where(occupation: "Rockstar")

改为使用procs

summary:
  Scopes in Mongoid must be procs that wrap criteria objects.
resolution:
  Change the scope to be a proc wrapped critera.

 Example:
   class Band
     include Mongoid::Document
     scope :inactive, ->{ where(active: false) }
   end

Mongoid v 7.0.3