Как настроить цепочечные области видимости на основе отношений в Mongoid? - PullRequest
12 голосов
/ 07 декабря 2011

Проблема исправлена ​​... Оказалось, что активный метод записи был перезаписан, теперь все работает как положено

Я пытаюсь настроить области, чтобы я мог сделать вызов, похожий на

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 (type) (первого связанного критерия) существует запись о конкурентах, и если я запускаю .count для запроса, я получаю общее количество конкурентов в базе данных.

В верхней части документации mongoid для областей указано, что все области являются цепочечными и могут применяться также к ассоциациям, что позже обсуждается в разделе отношений. К сожалению, я не видел подраздела отношений, не смог найти ни одной ссылки на область действия в разделе основных отношений.

Мне удалось получить следующее, чтобы вернуть желаемые результаты:

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

, но если какая-либо часть запроса разделяется на отдельный метод или область действия, она завершается неудачно и дает результат, который я показал выше.

Ответы [ 2 ]

10 голосов
/ 25 сентября 2013

прицелы

Как и в 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)

Обратите внимание, что определения оцениваются во время загрузки класса. За Оценка во время выполнения вы хотите убедиться, что определить с помощью proc или лямбда. В следующем примере первая дата установлена ​​как дата загрузки класса, где вторая область устанавливает дату в то время сфера называется.

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)

Именованные области видимости и методы классов, которые возвращают критерии, могут быть объединены в цепочку - в этом прелесть API мощных критериев Mongoid.

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)
0 голосов
/ 02 июня 2019

Хотя ответ @ MZaragoza был полным, похоже, этот синтаксис больше не разрешен:

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

Вместо этого используйте процы:

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

...