【问题标题】:Rails and polymorphic associationsRails 和多态关联
【发布时间】:2019-03-14 22:59:51
【问题描述】:

我有三个模型:UserCompanySubscription。我想要完成的是Subscription 属于UserCompany

为了尝试实现这一点,我引用了this guide,但由于记录创建不断回滚,我没有成功。

这是我的Company 模型:

# app/models/company.rb
class Company < ApplicationRecord
    has_many :subscriptions, dependent: :destroy, as: :imageable
end

这是我的User 模型:

# app/models/user.rb
class User < ApplicationRecord
  has_many :subscriptions, dependent: :destroy, as: :imageable
end

最后,这是我的Subscription 模型:

class Subscription < ApplicationRecord
    belongs_to :imageable, polymorphic: true
end

现在就迁移文件而言,这是我的Subscription 迁移文件:

class CreateSubscriptions < ActiveRecord::Migration[5.1]
  def change
    create_table :subscriptions do |t|
      t.references :imageable, polymorphic: true, index: true
      t.date :start_date
      t.date :stop_date

      t.timestamps
    end
  end
end

据我所见,这与指南显示的非常相似,但它一直在回滚。这是 rails 控制台的输出:

Loading development environment (Rails 5.1.6)
2.5.1 :001 > Subscription.create(imageable_id: 1, start_date: Time.now, stop_date: 2.days.from_now)
   (8.6ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.2ms)  BEGIN
   (0.3ms)  ROLLBACK
 => #<Subscription id: nil, imageable_type: nil, imageable_id: 1, start_date: "2018-10-10", stop_date: "2018-10-12", created_at: nil, updated_at: nil> 
2.5.1 :002 > 

以下是我的问题:

  1. 为什么会有imageable_type 字段?这是由t.references 创建的,如果是,我需要这个吗?我可以只使用imageable_id 而不是t.references,就像建议的另一部分显示的那样吗?
  2. 为什么会回滚?多态关联是在 Rails 5.x 中以不同方式完成的还是偶然的?
  3. 根据指南中显示的图表,如果一张图片属于imageable_id 4,那么如果有一个员工和一个 ID 为 4 的生产,那么一张图片将属于两者而不是一个或其他我想要完成的事情。正确吗?

【问题讨论】:

  • 您可以像User.first.subcriptions.create(start_date: Time.now, stop_date: 2.days.from_now) 那样创建订阅,而不是像这样创建订阅,所以它会自动采用 imagable id 和 imageble type
  • 啊,好的。这是有道理的,所以 imageable_type 实际上显示了正确的引用,因此 Company 和 User 的 ID 为 1 将通过其 imageable_type 进行区分,对吗?
  • 是的,让我补充一下答案
  • 明白了。谢谢!现在说得通了。

标签: ruby-on-rails activerecord


【解决方案1】:

对于多态关联,您还应该将imageable_typeimageable_id 一起传递。你不这样做,这就是为什么它不起作用,很可能(即可能有其他原因,我不知道,但这很明显)。

imageable_type 保存给定订阅关联的记录的类的名称。

【讨论】:

  • 这就是问题所在。我还了解到imageable_type 实际上引用了两个关联之一(例如CompanyUser)。我非常感谢您的帮助!
  • 是的,imageable_type 持有与Subscription 关联的记录的类的名称。
  • 谢谢@Marek,我也非常感谢您的帮助。
【解决方案2】:

在您的关联中,Imageable 类型将包含类名,而 imageble id 将包含该类的 id。所以如果你想为用户创建订阅,你可以像下面那样做

User.first.subcriptions.create(start_date: Time.now, stop_date: 2.days.from_now)

所以它会自动在 imageable id 中获取 First user 的 id 并将 "User" 作为 imageable 类型。

如果你想手动创建订阅,你必须像下面一样传递 imageable type 和 imageble id 这两个字段,

Subscription.create(imageable_id: 1, imageable_type: "User", start_date: Time.now, stop_date: 2.days.from_now)
  1. 为什么会有 imageable_type 字段?是不是由 t.references 如果是这样,我需要这个吗?我可以只使用 imageable_id 而不是建议的另一部分显示的 t.references?

=> imageable_type 将包含关联模型的类,例如“用户”或“公司”

  1. 为什么会回滚?是否完成了多态关联 在 Rails 5.x 中有所不同还是偶然的?

=> 不,你设置正确

  1. 根据指南中显示的图表,看起来如果一张图片属于 imageable_id 4,那么如果有一个员工和一个 ID 为 4 的生产,那么一张图片将属于两者而不是一个或其他就像我正在努力完成的。正确吗?

=> 这取决于 imageable_id 和 imageble_type ,所以通过这两者的结合,你会得到记录。如果 imageable_id 为 4 且 imageable_type 为“图片”,那么它将拍摄 id 为 4 的图片。

请查看this link了解

【讨论】:

  • 也感谢您深入而清晰的解释。我真的很感谢你的帮助。很高兴能解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多