имеет много отношений для полиморфной ассоциации - PullRequest
0 голосов
/ 27 августа 2018
class Sample
  has_many :pictures
end

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
  belongs_to :sample
end


class Employee < ApplicationRecord
  has_many :pictures, as: :imageable
end

class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

Какой должна быть ассоциация, чтобы получить весь продукт или сотрудника данного образца. Sample.first.pictures.map(&:imageable). Я хочу получить это как ассоциацию activerecord.

1 Ответ

0 голосов
/ 27 августа 2018

Обходной путь:

class Sample
  has_many :pictures
  has_many :imageable_employees, through: :pictures, source: :imageable, source_type: 'Employee'
  has_many :imageable_products, through: :pictures, source: :imageable, source_type: 'Product'
end

Использование:

sample = Sample.first
employees = sample.imageable_employees
products = sample.imageable_products

... см. документы

Объяснение:

Sample.first.pictures.map (&: гарантируемая).Я хочу получить это как ассоциацию activerecord.

... я не думаю, что это возможно, но вы все равно можете получить их все в виде массива.Причина в том, что нет таблицы (модели), которая соответствует ассоциации imageable, но вместо этого она соответствует ЛЮБОЙ модели, что усложняет запрос SQL, и поэтому я не думаю, что это возможно.

В качестве примера рассмотрим следующий запрос:

imageables_created_until_yesterday = Sample.first.something_that_returns_all_imageables.where('created_at < ?', Time.zone.now.beginning_of_day)

# what SQL from above should this generate? (without prior knowledge of what tables that the polymorphic association corresponds to)
# =>  SELECT "WHAT_TABLE".* FROM "WHAT_TABLE" WHERE (sample_id = 1 AND created_at < '2018-08-27 00:00:00.000000')

# furthermore, you'll notice that the SQL above only assumes one table, what if the polymorphic association can be at least two models / tables?

Альтернативное решение:

В зависимости от потребностей вашего приложения и «запросов», которые вы пытаетесь выполнить, вы можете илиможет не учитывать следующее, которое реализует модель abstract_imageable (реальная таблица), чтобы вы могли выполнять запросы.В этой abstract_imageable модели вы также можете добавить дополнительные атрибуты, которые, по вашему мнению, являются «общими» для всех «изображаемых» записей.

Не стесняйтесь переименовывать abstract_imageable

class Sample
  has_many :pictures
  has_many :abstract_imageables, through: :pictures
end

class Picture
  belongs_to :sample
  has_many :abstract_imageables
end

# rails generate model abstract_imageable picture:belongs_to imageable:references{polymorphic}
class AbstractImageable
  belongs_to :picture
  belongs_to :imageable, polymorphic: true
end

class Employee < ApplicationRecord
  has_many :abstract_imageables, as: :imageable
  has_many :pictures, through: :abstract_imageables
end

class Product < ApplicationRecord
  has_many :abstract_imageables, as: :imageable
  has_many :pictures, through: :abstract_imageables
end

Использование:

sample = Sample.first
abstract_imageables = sample.abstract_imageables

puts abstract_imageables.first.class
# => AbstractImageable

puts abstract_imageables.first.imageable.class
# => can be either nil, or Employee, or Product, or whatever model

puts abstract_imageables.second.imageable.class
# => can be either nil, or Employee, or Product, or whatever model

# your query here, which I assumed you were trying to do because you said you wanted an `ActiveRecord::Relation` object
abstract_imageables.where(...) 
...