class User < ApplicationRecord
has_and_belongs_to_many :profiles
def add_profile(profile)
self.profiles << profile unless self.profiles.include?(profile)
end
end
class Profile < ApplicationRecord
has_and_belongs_to_many :users
validates_uniqueness_of :linkedin_id, allow_nil: true
end
出于某种原因,我得到了
ActiveRecord::RecordInvalid: Validation failed: Linkedin has already been taken
on
self.profiles << profile unless self.profiles.include?(profile)
行。
在此之后,我在User.profiles记录中有重复。
有什么问题?
答案 0 :(得分:0)
使用has_and_belongs_to_many
可能不是最佳选择。
如果你有一个很常见的场景,用户可能会附上几个&#34;个人资料&#34;或者您想要一对多关系的帐户的外部OAuth凭证。
此示例使用通用uid
列而不是linkedin_id
,以便您可以对Facebook,Twitter或任何其他类型的帐户使用完全相同的逻辑。
class User < ActiveRecord::Base
has_many :profiles
end
class Profile < ActiveRecord::Base
belongs_to :user
end
这可以保证配置文件只能属于单个用户。您可能希望添加一些额外的唯一性约束。
class AddUserProviderIndexToProfiles < ActiveRecord::Migration
def change
add_index(:profiles, [:user_id, :provider], unique: true)
add_index(:profiles, [:uid, :provider], unique: true)
end
end
这在数据库级别强制执行,用户只能拥有一个具有给定提供程序的配置文件,并且可能只有一个配置文件具有给定:provider, :uid
组合。添加数据库safeguards against race conditions中的索引并提高性能。
您还需要进行应用程序级别验证,以避免因数据库驱动程序错误而导致应用程序崩溃!
class Profile < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :uid, scope: :provider
validates_uniqueness_of :user_id, scope: :provider
end