Estou tentando configurar 2 modelos (Entidades, Usuários) onde cada usuário pode trabalhar com várias entidades e cada entidade pode ter vários usuários trabalhando com elas. Quero que os relacionamentos sejam únicos, ou seja, um usuário não pode trabalhar 2 vezes com a mesma entidade e uma entidade não pode ter o mesmo usuário duas vezes.
Estou usando um relacionamento has_many e estou armazenando informações extras, como direitos de acesso, na classe "through".
class Entity < ApplicationRecord
has_many :user_entity_roles, dependent: :destroy
accepts_nested_attributes_for :user_entity_roles
has_many :users, through: :user_entity_roles, dependent: :restrict_with_error
end
class User < ApplicationRecord
has_many :user_entity_roles, dependent: :destroy
has_many :entities, through: :user_entity_roles, dependent: :restrict_with_error
end
class UserEntityRole < ApplicationRecord
belongs_to :entity, touch: true
belongs_to :user
end
Agora, por meio de um erro em um formulário que eu estava construindo, criei um relacionamento duplicado. Claro que posso tentar evitar isso não tendo erros em meus formulários, mas me pergunto se há uma maneira de forçar apenas combinações únicas de Usuários e Entidades?
Sim.
Adicionar um índice exclusivo
entity_id
euser_id
imporá exclusividade no nível do banco de dados:Observe que seu banco de dados não permitirá que você adicione esse índice até que você corrija os dados duplicados - por exemplo, excluindo as linhas duplicadas.
O índice fará com que o banco de dados rejeite quaisquer dados duplicados, o que causará um erro de driver de banco de dados. Para evitar esse erro e fornecer melhor feedback ao usuário, você quer uma validação em nível de aplicativo:
A validação detectará a maioria das possíveis duplicatas, mas não garante exclusividade por si só, pois é propensa a condições de corrida .
Se você quiser acionar essa validação ao salvar uma Entidade, você pode usar
validates_associated
: