[英]Uniqueness of has_many association
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
For some reason on production I get 由于某种原因,我得到了
ActiveRecord::RecordInvalid: Validation failed: Linkedin has already been taken
on 上
self.profiles << profile unless self.profiles.include?(profile)
line. self.profiles << profile unless self.profiles.include?(profile)
行。
And after this I have duplicates in User.profiles records. 之后,我在User.profiles记录中有重复项。
What is the problem? 问题是什么?
Using has_and_belongs_to_many
is probably not the best option here. 在这里使用
has_and_belongs_to_many
可能不是最佳选择。
If you have the quite common scenario where a user may attach several "profiles" or external OAuth credentials to their account you want a one to many relationship. 如果您遇到非常常见的情况,即用户可能将多个“配置文件”或外部OAuth凭据附加到其帐户,则需要一对多关系。
This example uses a generic uid
column instead of linkedin_id
so that you can use the exact same logic for Facebook, Twitter or any other sort of account. 本示例使用通用
uid
列而不是linkedin_id
以便您可以对Facebook,Twitter或任何其他类型的帐户使用完全相同的逻辑。
class User < ActiveRecord::Base
has_many :profiles
end
class Profile < ActiveRecord::Base
belongs_to :user
end
This guarantees that a profile can only belong to a single user. 这样可以保证配置文件只能属于一个用户。 You may want to add some additional uniqueness constraints.
您可能需要添加一些其他的唯一性约束。
class AddUserProviderIndexToProfiles < ActiveRecord::Migration
def change
add_index(:profiles, [:user_id, :provider], unique: true)
add_index(:profiles, [:uid, :provider], unique: true)
end
end
This enforces on the database level that a user can only have one profile with a given provider and that there may only be one profile with for a given :provider, :uid
combination. 这在数据库级别上强制要求,一个用户只能使用一个给定提供者的配置文件,并且对于给定的
:provider, :uid
组合:provider, :uid
可能只有一个配置文件。 Adding indexes in the database safeguards against race conditions and improves performance. 在数据库中添加索引可防止出现竞争情况并提高性能。
You will also want a application level validation to avoid the application crashing due to database driver errors! 您还将需要应用程序级别的验证,以避免由于数据库驱动程序错误而导致应用程序崩溃!
class Profile < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :uid, scope: :provider
validates_uniqueness_of :user_id, scope: :provider
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.