![](/img/trans.png)
[英]Why polymorphic association doesn't work for STI if type column of the polymorphic association doesn't point to the base model of STI?
[英]Can't get STI to act as polymorphic association on model
我有一個可以包含電子郵件和電話號碼的用戶模型,這兩個模型都是它們自己的模型,因為它們都需要某種形式的驗證。
所以我想做的是將Verification::EmailVerification
附加為email_verifications
並將Verification::PhoneVerification
為phone_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_verifications
和phone_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.