как получить все экземпляры объектов по полиморфному типу? - PullRequest
2 голосов
/ 02 ноября 2011

У меня установлены следующие модели:

class Sound < ActiveRecord::Base  
  has_many :tenders, :as => :tenderable
  belongs_to :event
end

class Stage < ActiveRecord::Base
  has_many :tenders, :as => :tenderable
  belongs_to :event
end

class Tender < ActiveRecord::Base
  attr_accessible :event_id, :user_id, :estimate, :tenderable_id, :tenderable_type
  belongs_to :tenderable, :polymorphic => :true
end

class Event < ActiveRecord::Base
  attr_accessible :name
  has_one :stage
  has_one :sound

  accepts_nested_attributes_for :stage, :allow_destroy => true
  accepts_nested_attributes_for :sound, :allow_destroy => true
end

К каждому событию прикреплены различные Tenderable'ы (например, stage, sound), я могу получить к ним доступ через Event.find (id) .tenderables, но мне нужно выяснить, какие «возможности» доступны, независимо от того, к какому событию они присоединены.

На данный момент у меня нет модели «Возможности», поскольку я пытаюсь сохранитьвсе просто.

На самом деле я хочу создать что-то вроде Tenderables.all, которое будет возвращать все звуки, сцены и все, что я определяю как тендерные.

Чтолучший способ добиться этого?

Спасибо;)

Ответы [ 3 ]

2 голосов
/ 02 ноября 2011

Afaik список всех Tenderables, в смысле вещей, к которым может быть прикреплен Tender, невозможно построить из базы данных или структуры модели. В базе данных вы сможете найти все Tenderable, к которым прикреплен Tender, но не простым способом (подумайте об объединении запросов для каждого tenderable_type).

Но основное свойство полиморфного отношения в действительности заключается в том, что к нему может быть присоединен любой объект, поэтому вам придется самостоятельно управлять полным списком объектов, которые могут иметь тендер.

Я не совсем уверен, почему вы этого хотите, но вы должны объединить Sound.all и Stage.all, и какая бы таблица ни стала позже.

Теперь, когда я пишу это, я думаю: чтобы объединиться, эти таблицы должны быть очень похожи. Если это так, в вашем случае вам может потребоваться ввести объект Tenderable для реального использования STI. Для того, что вы хотите прямо сейчас, это было бы лучшим решением.

Что бы ни было Tenderable должно поместиться в одной таблице с типом (Звук, Сцена, ...), и тогда вы получите нормальное отношение к Tenderable. Сцена или Звук наследуются от Tenderable. Затем вы можете легко выбрать все Tenderables или все звуки / сцены отдельно.

Надеюсь, это поможет.

2 голосов
/ 02 ноября 2011
Tender.select("DISTINCT tendable_type").collect(&:tendable_type).compact

Даст вам имя всех связанных Моделей, которые уже использовались хотя бы один раз.

Для всех объектов, которые были связаны с тенденцией

Tender.where("tendable_type IS NOT NULL").collect(&:tendable)
0 голосов
/ 27 апреля 2018

Принятый ответ правильный, но неэффективный.

  1. Чтобы выбрать все типы:

Tender.distinct.pluck(:tendable_type)

Это больше работает в базе данных и не требует создания каждого уникального объекта для вызова метода.

  1. Чтобы выбрать все объекты:

Tender.where.not(tendable: nil).includes(:tendable).map(&:tendable)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...