[英]Preventing duplicates via a custom foreign key in has_many :through
我正在尝试使用UserLocations连接表在User模型和Location模型之间实现双向has_many :through
关联。 这将允许使用内置的ActiveRecord方法来设置用户位置。 @user.locations = [<Location 1>, <Location 2>, ...]
。 我的目标不是将位置分别与用户相关联,而是让用户一次通过另一个字段:zip_code
一次或多次添加和删除它们。 这意味着,当用户添加邮政编码时,ActiveRecord应该在UserLocations中插入一条记录(类似于INSERT INTO user_locations (user_id, zip_code) VALUES (1, 12345)
)。 然后,在调用@user.locations
时,ActiveRecord应该通过:zip_code
加入并获取匹配的位置。 我的当前实现工作正常,只是为与邮政编码关联的每个位置都生成了一个对UserLocations的INSERT
。
class User < ActiveRecord::Base
has_many :user_locations
has_many :locations, through: :user_locations
end
class UserLocation < ActiveRecord::Base
belongs_to :user
belongs_to :location, primary_key: :zip_code, foreign_key: :zip_code
end
class Location < ActiveRecord::Base
has_many :user_locations, primary_key: :zip_code, foreign_key: :zip_code
has_many :users, through: :user_locations
end
我尝试过的事情:
validates_uniqueness_of :zip_code, scope: :user_id
仅引发验证错误并阻止所有记录的创建 has_many unique: true
不防止重复的数据库查询 add_index unique: true
(user_id, zip_code)
为(user_id, zip_code)
至少将防止创建重复的条目,但是我试图完全防止不必要的查询 喜欢使用的问题这一个指导还没有得到我任何接近。 不使用我自己的方法来获取/设置用户位置,是否可以做我想做的事情?
首先,我对Rails的经验还不是很丰富,但是我仍然会尽力帮助:)
我要做的是不使用邮政编码作为密钥。 当用户输入邮政编码时,您将在位置中查找该邮政编码:
@zip_code = Location.where(zipcode: user_input).first
@zip_code.user_locations.create!(user_id #some other stuff you want)
这样,您可以将位置的ID存储到用户位置中,并且不会重复。 然后,您可以通过加入UserLocation和Location来生成用户位置。
但是正如我所说,初学者可能是更好的方法。
如果我错了就阻止我:)
您的locations
表中有邮政编码(即111、222、333)。当用户为其自身选择邮政编码“ 111”时,他的记录将与现有locations
记录相关联。 但是当用户选择邮政编码“ 444”时,会创建一个新的locations
记录并链接到该用户。 下次选择“ 444”的用途将链接到该同一记录。
如果我的假设正确,那么您应该:
Location
模型中的validates_uniqueness_of :zip_code
(无范围) User
模型时,可以使用Location.find_or_create_by(params[:zipcode])
这是伪代码(请勿复制粘贴),我不完全知道您的代码是如何编写的,但是我的意思是让您了解一下find_or_create
,我相信这可能是您的解决方案
看起来您已正确设置了关联。
当您在rails中具有has_many
关联并且想要执行以下操作时:
@user.locations = [<Location 1>, <Location 2>, ...]
Rails将为数组中的每个位置创建单独的INSERT
语句,尽管它将为您执行批量DELETE
。 如果希望它执行批量INSERT
语句,则需要滚动自己的代码或查看activerecord-import gem来执行此操作。
至于重复项,如果仅执行上述代码,则除非该位置数组中存在重复项,否则不应有重复记录错误,在这种情况下,应首先对其调用uniq
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.