2013-07-31 60 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