假设我有一个PhoneNumber
多态模型。许多不同的型号可以have_many
phone_numbers。在前端的形式可以从模型到模型略有不同,但说我有一个用户表单,允许这样的电话号码:Rails验证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
什么是处理这个最高贵的方式?发送空字符串到服务器并解析它们对我来说似乎很肮脏。这里是代码,我到目前为止有:
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
这就是代码很多只是为了确保没有被提交失灵。当然有更好的方法?