Rails验证has_many与集合

时间:2016-09-20 21:25:14

标签: ruby-on-rails ruby has-many

假设我有一个PhoneNumber多态模型。许多不同的模型可以have_many phone_numbers。前端的表单可能因模型而略有不同,但是我说有一个用户表单允许这样的电话号码:

用户:

first phone: ___________

second phone: __________

third phone: ___________

<小时/> 用户模型has_many电话号码和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

这是一大堆代码,只是为了确保没有任何内容无序提交。当然有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

电话号码的重要性是什么? 如果您只想省略空字符串的字段,请尝试https://github.com/rubiety/nilify_blanks

我不确定为什么要首先在用户模型中验证电话号码。为什么不在他们所属的模型中验证它们呢?