2016-11-22 3 views
0

Каков предпочтительный способ выбора конкретной записи из отношения has_many для определенной модели в Rails? (Я использую Rails 5.)Выбор одного из отношений has_many в Rails

У меня есть модель User и модель Picture которые связаны с помощью следующего кода:

class User < ApplicationRecord 
    has_many :pictures, as: :imageable 
    # ... 
end 

class Picture < ApplicationRecord 
    belongs_to :imageable, polymorphic: true 
    # ... 
end 

То, что я хочу сделать, это позволить User установить изображение профиля из связанных с ним изображений, поэтому я могу позвонить @user.profile_picture на объект User и получить изображение профиля.

+0

Вам необходимо сохранить его в 'User', возможно, как' has_one'. Вы можете вызвать это отношение 'profile_picture' :) –

+0

Итак' has_one: profile_picture, as:: imageable'? Как это сохраняется в БД? Мне нужно создать модель ProfilePicture? – mindseyeblind

+0

Да, и не забывайте о миграции для этого отношения. –

ответ

0

Вы можете добавить дополнительные отношения один к одному.

# create by running: 
# rails g migration AddPrimaryPictureToUser 
class AddPrimaryPictureToUser < ActiveRecord::Migration[5.0] 
    def change 
    add_column :users, :primary_picture_id, :integer 
    add_index :users, :primary_picture_id 
    add_foreign_key :users, :pictures, column: :primary_picture_id 
    end 
end 

class User < ApplicationRecord 
    has_many :pictures, as: :imageable 
    # This should be belongs_to and not has_one as the foreign key column is 
    # on the users table 
    belongs_to :primary_picture, 
      class_name: 'Picture', 
      optional: true 
end 


class Picture < ApplicationRecord 
    belongs_to :imageable, polymorphic: true 
    has_one :primary_user, 
      foreign_key: 'primary_picture_id', 
      class_name: 'User' 
    # ... 
end 

Основная причина, чтобы сделать это таким образом, по сравнению, например, логический флаг на pictures таблицы является то, что наличие отдельного отношения позволяет легко присоединиться, который имеет важное значение для избежания N + 1 запросы, которые являются проблемой, если вы перечисляете группу пользователей вместе с их основным изображением.

@users = User.includes(:primary_picture).all 
+0

Интересно. Можете ли вы просмотреть решение, предложенное комментатором выше, и рассказать мне о преимуществах/компромиссах каждой архитектуры? – mindseyeblind

+0

Использование полиморфизма в этом взаимно-однозначном отношении является ошибкой, поскольку оно не позволит вам осуществлять прямое соединение между пользователями и их основным изображением. Использование полиморфизма также означает, что вы теряете ссылочную целостность, так как связь не поддерживается внешним ключом. – max

+0

Хорошо, спасибо! Почему параметр «optional: true» установлен только в 'User', а не' Picture'? – mindseyeblind

Смежные вопросы