em um objeto ActiveModel, como faço para verificar a exclusividade?
No excelente post do blog de Bryan Helmkamp chamado "7 padrões para refatorar modelos ActiveRecord Fat", ele menciona usandoForm Objects
para abstrair formas de múltiplas camadas e parar de usaraccepts_nested_attributes_for
.
Editar: vejaabaixo para uma solução.
Eu praticamente dupliquei a amostra de código dele, pois tive o mesmo problema a 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
Uma das coisas diferentes no meu pedaço de código, é que eu preciso validar osingularidade do nome da conta (e e-mail do usuário). Contudo,ActiveModel::Validations
não tem umuniqueness
validador, como é suposto ser uma variante deActiveRecord
.
Eu percebi que existem três maneiras de lidar com isso:
Escreva meu próprio método para verificar isso (parece redundante)Incluir ActiveRecord :: Validações :: UniquenessValidator (tentei isto, não funcionou)Ou adicione a restrição na camada de armazenamento de dadosEu preferiria usar o último. Mas então eu fiquei me perguntandocomo Eu implementaria isso.
Eu poderia fazer algo parecido(metaprogramação, eu precisaria modificar algumas outras á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
Mas agora eu tenho duas verificações em execução na minha turma, primeiro eu usovalid?
e então eu uso umrescue
declaração para as restrições de armazenamento de dados.
Alguém sabe de uma boa maneira de lidar com esse problema? Seria melhor talvez escrever meu próprio validador para isso (mas então eu teria duas consultas ao banco de dados, onde, idealmente, uma seria suficiente).