我正在尝试使用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
加入并获取匹配的位置。我当前的实现工作正常,除了为与邮政编码关联的每个位置生成一个INSERT
到UserLocations。
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)
- 至少会阻止创建重复的条目,但我试图完全阻止不必要的查询使用像this one这样的问题作为指导并没有让我更接近。如果不使用我自己的方法获取/设置用户位置,我正在尝试做什么?
答案 0 :(得分:0)
首先,我还没有很好的铁杆经验,但我仍然会尝试帮助:)
我要做的是不使用zipcodes作为密钥。当用户输入邮政编码时,您可以在位置中查找代码:
@zip_code = Location.where(zipcode: user_input).first
@zip_code.user_locations.create!(user_id #some other stuff you want)
这样,您可以将位置的ID存储到用户位置,并且不会重复。然后,您可以通过加入UserLocation和Location来生成用户位置。
但正如我所说,作为我的初学者,可能有更好的方法来做这件事。
答案 1 :(得分:0)
如果我错了,请阻止我:)
你的locations
表格中有拉链码(即:111,222,333)当用户为他自己选择一个'111'的邮政编码时,他的记录与现有的locations
记录相关联;但是当用户选择“444”的邮政编码时,会创建一个新的locations
记录并链接到该用户。选择“444”的下一个用途将链接到同一记录。
如果我的假设是正确的,你应该:
validates_uniqueness_of :zip_code
型号中的Location
(无范围)
创建/更新时{i>模型中的User
这是伪代码(不要复制粘贴它),我不知道你的代码是如何写的,但我的观点是你看看Location.find_or_create_by(params[:zipcode])
,我相信它可能是你的解决方案
答案 2 :(得分:0)
看起来您正确设置了关联。
如果您在rails中有has_many
关联,并希望执行以下操作:
@user.locations = [<Location 1>, <Location 2>, ...]
Rails会为数组中的每个位置创建单独的INSERT
语句,尽管它会为您执行批量DELETE
。如果您希望它执行批量INSERT
语句,则需要滚动自己的代码或查看activerecord-import gem来执行此操作。
对于重复项,如果您只是执行上述代码,则除非该位置数组中存在重复项,否则不应存在重复的记录错误,在这种情况下,您应首先在其上调用uniq
。 / p>