Tengo un estándar de muchos-a-muchos relación entre los usuarios y los roles en mi aplicación Rails:rieles idioma para evitar duplicados en has_many: a través de
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
quiero para asegurarse de que un usuario sólo puede asignarse cualquier rol una vez Cualquier intento de insertar un duplicado debe ignorar la solicitud, no arrojar un error o causar una falla de validación. Lo que realmente quiero representar es un "conjunto", donde insertar un elemento que ya existe en el conjunto no tiene ningún efecto. {1,2,3} U {1} = {1,2,3}, no {1,1,2,3}.
que se dan cuenta de que puedo hacerlo de esta manera:
user.roles << role unless user.roles.include?(role)
o mediante la creación de un método de envoltura (por ejemplo add_to_roles(role)
), pero esperaba por alguna forma idiomática para que sea automático a través de la asociación, de manera que Puedo escribir:
user.roles << role # automatically checks roles.include?
y simplemente hace el trabajo por mí. De esta forma, no tengo que acordarme de buscar dúplex o usar el método personalizado. ¿Hay algo en el marco que me falta? Primero pensé que la opción: uniq a has_many lo haría, pero básicamente es solo "seleccionar distinto".
¿Hay alguna manera de hacerlo declarativamente? Si no, ¿tal vez mediante el uso de una extensión de asociación?
Aquí hay un ejemplo de cómo falla el comportamiento por defecto:
>> 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">]
No funciona así. Actualizaré la publicación para incluir la prueba. – KingPong
Gracias, probaré la extensión de asociación. – KingPong
Eso funcionó perfectamente. ¡Gracias! La parte que me faltaba cuando probé algo como esto fue el bit proxy_owner. – KingPong