2016-09-20 8 views
2

Скажем, у меня есть полиморфная модель 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 

Это много кода, просто чтобы убедиться, что ничто не представлено в порядке. Неужели есть лучший способ?

ответ

0

Какова важность заказа номеров телефонов? Если вы просто хотите опустить поля, которые являются пустыми, попробуйте https://github.com/rubiety/nilify_blanks

Я не уверен, почему вы вначале проверяли номера телефонов в модели пользователя. Почему бы не проверить их в модели, к которой они принадлежат?