en un objeto ActiveModel, ¿cómo verifico la singularidad?

En la excelente publicación de blog de Bryan Helmkamp llamada "7 patrones para refactorizar los modelos de ActiveRecord de grasa", menciona que usaForm Objects para abstraer formas multicapa y dejar de usaraccepts_nested_attributes_for.

Editar: verabajo para una solución.

He duplicado casi exactamente su ejemplo de código, ya que tuve el mismo problema que resolver:

class Signup
  include Virtus

  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_reader :user
  attr_reader :account

  attribute :name, String
  attribute :account_name, String
  attribute :email, String

  validates :email, presence: true
  validates :account_name,
    uniqueness: { case_sensitive: false },
    length: 3..40,
    format: { with: /^([a-z0-9\-]+)$/i }

  # Forms are never themselves persisted
  def persisted?
    false
  end

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

private

  def persist!
    @account = Account.create!(name: account_name)
    @user = @account.users.create!(name: name, email: email)
  end
end

Una de las cosas diferentes en mi código, es que necesito validar elunicidad del nombre de cuenta (y correo electrónico del usuario). Sin embargo,ActiveModel::Validations no tiene ununiqueness validador, ya que se supone que es una variante no respaldada por base de datos deActiveRecord.

Pensé que hay tres maneras de manejar esto:

Escribe mi propio método para verificar esto (se siente redundante)Incluya ActiveRecord :: Validations :: UniquenessValidator (intente esto, no lo hizo funcionar)O agregue la restricción en la capa de almacenamiento de datos

Preferiría usar el último. Pero luego me sigo preguntandocómo Yo implementaría esto.

Yo podria hacer algo como(metaprogramación, necesitaría modificar algunas otras áreas):

  def persist!
    @account = Account.create!(name: account_name)
    @user = @account.users.create!(name: name, email: email)
  rescue ActiveRecord::RecordNotUnique
    errors.add(:name, "not unique" )
    false
  end

Pero ahora tengo dos cheques corriendo en mi clase, primero usovalid? y luego uso unrescue Declaración para las restricciones de almacenamiento de datos.

¿Alguien sabe de una buena manera de manejar este problema? ¿Sería mejor tal vez escribir mi propio validador para esto (pero luego tendría dos consultas a la base de datos, donde idealmente una sería suficiente)?

Respuestas a la pregunta(2)

Su respuesta a la pregunta