Скажем, у меня есть полиморфная модель PhoneNumber
. Многие модели могут have_many
phone_numbers. Формы на веб-интерфейсе, могут незначительно отличаться от модели к модели, но говорят, что у меня есть форма пользователя, что позволяет телефонные номера, как это:Rails validate has_many ассоциация против других объектов в коллекции
пользователя:
first phone: ___________
second phone: __________
third phone: ___________
Модель пользователя
has_many
phone_numbers и
accepts_nested_attributes
для них. Скажем, у меня есть требование, чтобы телефоны были заполнены в порядке.
Я предполагаю, что это означает, что все поля являются пустыми и позволяют серверу выполнять проверки. Но как он узнает, что один PhoneNumber
один или нет?
Например, если представить эту форму:
Пользователь:
first phone: ___________
second phone: 123-456-7890
third phone: 123-456-7890
Там должна быть ошибка, которая выглядит примерно так:
second phone: 123-456-7890 "error: cannot add phone number when 1st number is blank"
Или если бы я был более сложная форма представляется:
Пользователь:
first phone: ___________
second phone: 123-456-7890 "error: cannot add phone number when 1st number is blank"
third phone: 123-456-7890
fourth phone: ___________
fifth phone: 123-456-7890 "error: cannot add phone number when 4th number is blank"
sixth phone: 123-456-7890
Что самое Elegent способ обработки этого? Отправка пустых строк на сервер и разбор их кажутся мне грязными. Вот код, который я до сих пор:
class User < ActiveRecord::Base
has_many :phone_numbers, as: :callable
validate :phones_cant_be_incorrect_order
private
def phones_cant_be_incorrect_order
return unless phone_numbers.size > 1
intentional_phone_numbers.each.with_index do |_phone, i|
previous_number = i.ordinalize
errors.add(
:"phone_numbers.number",
"can't add phone number when #{previous_number} number is blank"
) unless previous_number_present?(phone_numbers, i)
end
end
# Parse out empty strings
# Example: If only first_phone was filled out, delete all other empty strings.
def intentional_phone_numbers
last_number_present = phone_numbers.reverse.find { |x| x.number.present? }
right_index = phone_numbers.index(last_number_present)
bad = phone_numbers[(right_index + 1)..-1]
self.phone_numbers = phone_numbers - bad
end
def previous_number_present?(array, index)
return true if index.zero?
array[index - 1].number.present?
end
end
Это много кода, просто чтобы убедиться, что ничто не представлено в порядке. Неужели есть лучший способ?