2013-07-31 61 views
0

我试图使用UserLocations连接表实现用户模型和位置模型之间的双向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是为与邮政编码相关联的每个位置生成的。通过has_many中的自定义外键防止重复:通过

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 - 不防止重复DB查询
  • add_index unique: true(user_id, zip_code) - 至少可以防止重复条目被创建,但我试图完全防止不必要的查询

使用像this one这样的问题作为指导并没有让我更接近。是我试图做到不使用我自己的方法来获取/设置用户位置?

+0

Josh,如果其中一个答案帮助你需要接受它 – Benj

回答

0

首先,我不是很在轨经验,但我还是会尽力帮助:)

我会做的是不是可以使用邮政编码作为重点。当用户输入邮政编码您查找代码中的位置:

@zip_code = Location.where(zipcode: user_input).first 
@zip_code.user_locations.create!(user_id #some other stuff you want) 

这样你的位置的ID存储到用户的位置,并没有重复制成。然后,您可以通过加入UserLocation和Location来生成用户位置。

但正如我所说,有可能这样做,因为我是初学者的一个更好的办法。

+0

我认为你基本上建议直接将用户关联到位置,所以连接表具有'user_id,location_id',它可以防止重复并生成'@user。位置可用等等。这并没有达到我添加/删除单个查询操作的目标(因为一个邮政编码可以有多个位置)。我的应用程序旨在允许许多这些操作快速执行(即它们需要便宜),而位置查找可能相对昂贵。我误解了你的建议吗? –

0

停止我,如果我错了:)

您的locations表邮编(即:111,222,333),当用户选择的“111”一个邮编为他自己,他的纪录是与现有的locations记录相关联;但是,当用户选择的邮编是创建“444”的新locations记录,并链接到该用户。接下来使用那个选择'444'将被链接到这个相同的记录。

如果如果正确的话我的假设,你应该有:

  • validates_uniqueness_of :zip_code(无范围)在Location模型
  • User模式,同时创建/更新,你可以使用Location.find_or_create_by(params[:zipcode])

这是伪代码(不要复制粘贴),我不完全知道你的代码是如何写的,但我的观点是你有看看find_or_create,我相信它可能是你的解决方案

0

看起来您正确设置了关联。

当你在Rails中has_many协会,并希望做这样的事情:

@user.locations = [<Location 1>, <Location 2>, ...] 

Rails会创建单独的INSERT报表阵列中的每个位置,虽然会做批量DELETE你。如果您希望它执行批量INSERT语句,则需要滚动您自己的代码或查看activerecord-import gem来执行此操作。

至于重复,如果你只是做上面的代码,不应该有重复的记录错误,除非该位置数组中有重复,在这种情况下,你应该首先调用uniq