繁体   English   中英

通过has_many中的自定义外键防止重复:through

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM