簡體   English   中英

無法讓STI充當模型上的多態關聯

[英]Can't get STI to act as polymorphic association on model

我有一個可以包含電子郵件和電話號碼的用戶模型,這兩個模型都是它們自己的模型,因為它們都需要某種形式的驗證。

所以我想做的是將Verification::EmailVerification附加為email_verifications並將Verification::PhoneVerificationphone_verifications ,它們都是Verification STI。

class User < ApplicationRecord
  has_many :email_verifications, as: :initiator, dependent: :destroy
  has_many :phone_verifications, as: :initiator, dependent: :destroy

  attr_accessor :email, :phone

  def email
    @email = email_verifications.last&.email
  end

  def email=(email)
    email_verifications.new(email: email)
    @email = email
  end

  def phone
    @phone = phone_verifications.last&.phone
  end

  def phone=(phone)
    phone_verifications.new(phone: phone)
    @phone = phone
  end
end

class Verification < ApplicationRecord
  belongs_to :initiator, polymorphic: true
end

class Verification::EmailVerification < Verification
  alias_attribute :email, :information
end

class Verification::PhoneVerification < Verification
  alias_attribute :phone, :information
end

但是,通過上述設置,我得到了uninitialized constant User::EmailVerification的錯誤。 我不確定我要去哪里。

如何構造此結構,以便可以在用戶模型上訪問email_verificationsphone_verifications

使用STI時,您不需要(或想要)多態關聯。

多態關聯是圍繞對象關系阻抗不匹配問題的黑客,這些對象關系阻抗不匹配問題用於設置指向多個表的單個關聯。 例如:

class Video
  has_many :comments, as: :commentable
end

class Post
  has_many :comments, as: :commentable
end

class Comment
  belongs_to :commentable, polymorphic: true
end

應當謹慎使用它們的原因是,沒有參照完整性,並且存在很多與聯接和渴望加載記錄相關的問題,而STI沒有這些記錄,因為您有指向單個表的“真實”外鍵列。

Rails中的STI僅使用ActiveRecord讀取type列來查看在加載記錄時實例化哪個類的事實,該記錄也用於多態關聯。 否則,它與多態無關。

當您設置與STI模型的關聯時,您只需要創建與基本繼承類的關聯,並且Rails將在加載關聯記錄時通過讀取type列來處理解析類型:

class User < ApplicationRecord
  has_many :verifications
end

class Verification < ApplicationRecord
  belongs_to :user
end

module Verifications 
  class EmailVerification < ::Verification
    alias_attribute :email, :information
  end
end

module Verifications 
  class PhoneVerification < ::Verification
    alias_attribute :email, :information
  end
end

您還應該將模型嵌套在模塊而不是類中。 這部分是由於模塊查找中的錯誤直到Ruby 2.5才解決,也歸因於約定。

然后,如果您想與Verification的子類型建立更具體的關聯,則可以通過以下方式實現:

class User < ApplicationRecord
  has_many :verifications
  has_many :email_verifications, ->{ where(type: 'Verifications::EmailVerification') },
          class_name: 'Verifications::EmailVerification'
  has_many :phone_verifications, ->{ where(type: 'Verifications::PhoneVerification') },
          class_name: 'Verifications::PhoneVerification'
end

如果你想別名關聯user ,並調用它initiator你做它通過提供類名選項將belongs_to關聯,並指定在該外鍵has_many協會:

class Verification < ApplicationRecord
  belongs_to :initiator, class_name: 'User'
end

class User < ApplicationRecord
  has_many :verifications, foreign_key: 'initiator_id'
  has_many :email_verifications, ->{ where(type: 'Verifications::EmailVerification') },
          class_name: 'Verifications::EmailVerification',
          foreign_key: 'initiator_id'
  has_many :phone_verifications, ->{ where(type: 'Verifications::PhoneVerification') },
          class_name: 'Verifications::PhoneVerification',
          foreign_key: 'initiator_id'
end

但是,這與多態無關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM