Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

300
Visualizações
¿Es posible agregar una restricción de unicidad entre dos modelos diferentes pero asociados?

Tengo los modelos Account y User . Ambos modelos tienen un atributo de email .

Una cuenta has_many :users y un usuario belongs_to :account

Me gustaría validar la unicidad del email en ambos modelos cuando se crea una Account , por lo que el correo electrónico de la Account no es válido si lo toma un User (ya que el correo electrónico de la cuenta luego se convierte en el correo electrónico del usuario administrador).

Agregué un alcance a la restricción de email en el modelo Account pero no funciona (el formulario no se rechaza).

Modelo de cuenta:

 has_many :users validates :email, uniqueness: { scope: :users, case_sensitive: false }

¿Cuál es la forma correcta de implementar esto? ¿Necesito agregar un índice a la base de datos?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Una validación a nivel de aplicación en realidad no garantiza la unicidad de sus datos; simplemente detecta muchos de los casos en los que los usuarios intentan ingresar duplicados y proporciona comentarios.

Entonces, si bien podría implementar ingenuamente una validación personalizada que consulte ambas tablas, ni siquiera sobrevivirá a la condición de carrera causada por un ciudadano mayor que hace doble clic o cualquier método de inserción que eluda las validaciones.

Diagrama de flujo de solicitudes paralelas de Thoughtbot

Dado que no hay forma (AFAIK) de crear índices en las tablas, es posible que desee reestructurar su dominio y agregar un "propietario" (llámelo como quiera) a la tabla de cuentas:

 class AddOwnerToAccounts < ActiveRecord::Migration[6.1] def change add_reference :accounts, :owner, null: false, foreign_key: { to_table: 'users' } end end
 class Account < ApplicationRecord has_many :users belongs_to :owner, class_name: 'User', inverse_of: :owned_accounts delegate :email, to: :owner end
 class User < ApplicationRecord belongs_to :account has_many :owned_accounts, class_name: 'Account', foreign_key: :owner_id, inverse_of: :owner end
over 4 years ago · Santiago Trujillo Relatório

0

Este es un método alternativo basado en una tabla separada y una asociación polimórfica:

 class CreateEmailAddresses < ActiveRecord::Migration[6.1] def change create_table :email_addresses do |t| t.string :email, unique: true t.references :entitity, polymorphic: true t.timestamps end add_index :email_addresses, [:entity_type, :entity_id], unique: true end end
 class EmailAddress < ApplicationRecord validates_uniqueness_of :email validates_uniqueness_of :entity_id, scope: :entity_type belongs_to :entity, polymorphic: true end
 class User < ApplicationRecord has_one :email_address, as: :entity, dependent: :destroy delegate :email, to: :email_address accepts_nested_attributes_for :email_address end
 class Account < ApplicationRecord has_one :email_address, as: :entity, dependent: :destroy delegate :email, to: :email_address accepts_nested_attributes_for :email_address end

Evita tener que reestructurar su dominio o crear un usuario simplemente para crear un correo electrónico, pero causará problemas con las bibliotecas de autenticación como Devise, además de la falta de una clave externa real para garantizar la integridad referencial, lo que puede generar registros huérfanos.

En mi opinión, no es una gran solución, ya que lo más probable es que cree tantos problemas como los que resuelve.

over 4 years ago · Santiago Trujillo Relatório

0

Esto solo se puede lograr con un método de validación personalizado .

 validate :email_unique_for_account_and_user private def email_unique_for_account_and_user if User.where(email: email).where.not(id: id).exists? || Account.where(email: email).where.not(id: id).exists? errors.add(:email, :taken) end end

En mi opinión, no es posible definir un índice único en varias tablas de bases de datos.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda