【问题标题】:Selecting one of a has_many relation in Rails在 Rails 中选择 has_many 关系之一
【发布时间】:2023-03-22 10:41:02
【问题描述】:

为 Rails 中的特定模型从 has_many 关系中选择特定记录的首选方法是什么? (我使用的是 Rails 5。)

我有一个模型User 和一个模型Picture,它们通过以下代码关联:

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

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

我想做的是允许User 从与其关联的图像中设置个人资料图片,这样我就可以在User 对象上调用@user.profile_picture 并检索个人资料图片。

【问题讨论】:

  • 您需要将其存储在User 中,可能是has_one 关系。您可以将此关系称为profile_picture :)
  • 所以has_one :profile_picture, as: :imageable?这如何在数据库中持续存在?我需要创建ProfilePicture 模型吗?
  • 是的,不要忘记这个关系的迁移。
  • 所以总结一下:has_one :profile_pictureUser 模型中。 has_one :picture, as: :imageablebelongs_to :user 的新 ProfilePicture 模型。就这些吗?
  • 是的!总结一下。

标签: ruby-on-rails associations ruby-on-rails-5 activemodel


【解决方案1】:

您可以添加额外的一对一关系。

# 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

【讨论】:

  • 有趣。您能否回顾一下上述评论者建议的解决方案并告诉我每种架构的好处/权衡?
  • 在这种一对一关系中使用多态性是错误的,因为它不允许您直接连接用户和他们的主图像。使用多态还意味着您将失去参照完整性,因为关系没有外键支持。
  • 好的,谢谢!为什么optional: true 只设置在User 而不是Picture
  • 在 Rails 5 中,belongs_to 的默认值更改为 optional: false,这意味着模型会自动验证关联的存在 - has_one 不是这种情况。
猜你喜欢
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多