Usted puede agregar singularidad a unirse a la mesa
add_index :users_roles, [ :user_id, :role_id ], :unique => true, :name => 'by_user_and_role'
ver In a join table, what's the best workaround for Rails' absence of a composite key?
Su base de datos lanzará una excepción a continuación, que usted tiene manejar.
no sé ninguna lista para utilizar la validación de los carriles para este caso, pero se puede añadir su validación como esto:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles, :before_add => :validates_role
me acaba de caer en silencio la llamada base de datos e informar éxito.
def validates_role(role)
raise ActiveRecord::Rollback if self.roles.include? role
end
ActiveRecord :: Rollback es capturado internamente pero no resubía.
Editar
No utilice la parte en la que estoy añadiendo una validación personalizada. Funciona un poco, pero hay mejores alternativas.
Uso :uniq
opción asociación como @Spyros sugirió en otra respuesta:
class Parts < ActiveRecord::Base
has_and_belongs_to_many :assemblies, :uniq => true, :read_only => true
end
(fragmento de este código es de Rieles Guías de la versión 3). Lea en Rails Guides v 3.2.13 busque 4.4.2.19: uniq
Rails Guide v.4 específicamente advierte contra el uso de include?
para comprobar la exclusividad debido a las posibles condiciones de carrera.
Se mantiene la parte sobre cómo agregar un índice para unir la tabla.
¡Gracias por esto! Terminé usando esto para una instancia HABTM de un usuario y grupos (esencialmente el mismo tipo de configuración de roles). – dennismonsewicz
Es un poco desagradable que la deduplicación no se maneje automáticamente para las asociaciones de habtm, a diferencia de ': has_many'. – prusswan
publicado después de la edición. He publicado esta respuesta y se me olvidó. Y luego me encontré con un problema relacionado y recordé que tengo una respuesta, la gente mantiene la votación ascendente y la revisé y ¡OMG! ¡Qué estaba pensando! Espero que nadie tenga ningún problema porque usó mi respuesta. Me siento lo suficientemente mal sin eso. Bueno, esa es una lección para todos nosotros. Dejas una respuesta descuidada con prisa en Stackoverflow y te olvidas de ella, pero llegará el momento en que saltará y te morderá por el culo. –