na obiekcie ActiveModel, jak mogę sprawdzić unikalność?
W doskonałym blogu Bryana Helmkampa zatytułowanym „7 wzorów do modeli Refactor Fat ActiveRecord„, wspomina, używającForm Objects
abstrahować od formularzy wielowarstwowych i przestać ich używaćaccepts_nested_attributes_for
.
Edytuj: zobaczponiżej na rozwiązanie.
Prawie dokładnie zduplikowałem jego próbkę kodu, ponieważ miałem ten sam problem do rozwiązania:
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
Jedną z rzeczy innych w moim fragmencie kodu jest to, że muszę zweryfikowaćwyjątkowość nazwy konta (i e-mail użytkownika). Jednak,ActiveModel::Validations
nie mauniqueness
walidator, ponieważ powinien być wariantem bez kopii zapasowej bazy danychActiveRecord
.
Pomyślałem, że są na to trzy sposoby:
Napisz własną metodę, aby to sprawdzić (wydaje się zbędna)Dołącz ActiveRecord :: Validations :: UniquenessValidator (próbowałem tego, nie udało się go uruchomić)Lub dodaj ograniczenie w warstwie przechowywania danychWolałbym użyć ostatniego. Ale potem się zastanawiamw jaki sposób Zaimplementowałbym to.
Mógłbym zrobić coś takiego(metaprogramowanie, musiałbym zmodyfikować inne obszary):
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
Ale teraz mam dwie kontrole w mojej klasie, najpierw używamvalid?
a potem używamrescue
oświadczenie o ograniczeniach dotyczących przechowywania danych.
Czy ktoś zna dobry sposób na rozwiązanie tego problemu? Czy byłoby lepiej, gdyby napisał do tego mój własny walidator (ale wtedy miałbym dwa zapytania do bazy danych, gdzie najlepiej byłoby jedno).