我有一個標準的多對許多用戶和角色在我的Rails應用程序之間的關係:Rails的成語,以避免重複中的has_many:通過
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
我想確保一個用戶只能分配任何角色一次。任何嘗試插入重複都應該忽略該請求,不會拋出錯誤或導致驗證失敗。我真正想要表達的是一個「集合」,其中插入集合中已經存在的元素不起作用。 {1,2,3} U {1} = {1,2,3},而不是{1,1,2,3}。
我知道我能做到這一點是這樣的:通過創建一個包裝方法(如add_to_roles(role)
)
user.roles << role unless user.roles.include?(role)
或者,但我希望對一些慣用的方法,使其通過關聯自動,這樣我可以寫:
user.roles << role # automatically checks roles.include?
它只是爲我做的工作。這樣,我不必記得檢查dups或使用自定義方法。我錯過了框架中的某些東西嗎?我首先想到:has_many的uniq選項可以實現,但它基本上只是「選擇不同」。
有沒有辦法做到這一點聲明?如果沒有,也許通過使用關聯擴展?
這裏的默認行爲是如何失敗的一個例子:
>> u = User.create User Create (0.6ms) INSERT INTO "users" ("name") VALUES(NULL) => #<User id: 3, name: nil> >> u.roles << Role.first Role Load (0.5ms) SELECT * FROM "roles" LIMIT 1 UserRole Create (0.5ms) INSERT INTO "user_roles" ("role_id", "user_id") VALUES(1, 3) Role Load (0.4ms) SELECT "roles".* FROM "roles" INNER JOIN "user_roles" ON "roles".id = "user_roles".role_id WHERE (("user_roles".user_id = 3)) => [#<Role id: 1, name: "1">] >> u.roles << Role.first Role Load (0.4ms) SELECT * FROM "roles" LIMIT 1 UserRole Create (0.5ms) INSERT INTO "user_roles" ("role_id", "user_id") VALUES(1, 3) => [#<Role id: 1, name: "1">, #<Role id: 1, name: "1">]
它不這樣工作。我會更新帖子以包含測試。 – KingPong 2009-08-22 17:24:55
謝謝,我會嘗試關聯擴展。 – KingPong 2009-08-24 15:42:15
完美運作。謝謝!當我嘗試類似這樣的事情時,我錯過的部分是proxy_owner位。 – KingPong 2009-08-24 18:05:03