繁体   English   中英

如何在Ruby on Rails模型中进行条件验证?

[英]How can I do conditional validation in a Ruby on Rails Model?

我有可以participantsstudy 我有一个simple_form ,用户可以在其中添加参与者。 它看起来有点像一张桌子:

name | company | email OR mobile | timezone
name | company | email OR mobile | timezone
name | company | email OR mobile | timezone

默认情况下,该屏幕具有三个字段集行,并且用户可以根据需要添加更多行。 每行是一个参与者。

我希望我的participant模型仅验证已填写的行,而忽略空白行,因为即使我们默认向用户显示三行,也不是全部都是必填字段。

这是app/models/participants.rb的相关部分。

class Participant < ApplicationRecord
  belongs_to :study

  validates :name, presence: true
  validates :company, presence: true
  validates :time_zone, presence: true

  if :channel == 'sms'
    validates :mobile_number, presence: true
  elsif :channel == 'email'
    validates :email, presence: true
  end
end

participants_controller.rb我有:

def index
  3.times { @study.participants.build } if @study.participants.length.zero?
end

问题是我得到一个错误,因为simple_form认为所有三个字段都是必需的,而不仅仅是第一行。

Rails的验证器接受以下条件:

validates :mobile_number, presence: true, if: Proc.new { |p| p.study.channel == 'sms' }
validates :email,         presence: true, if: Proc.new { |p| p.study.channel == 'email' }

默认情况下,所有输入都是必需的。 当表单对象包含ActiveModel :: Validations(例如,在Active Record模型中发生)时,仅当存在状态验证时才需要字段。 否则,“简单表单”会将字段标记为可选。 出于性能原因,在使用条件选项(例如:if和:unless)的验证中将跳过此检测。

当然,可以根据需要覆盖任何输入的必需属性:

<%= simple_form_for @user do |f| %>
  <%= f.input :name, required: false %>
  <%= f.input :username %>
  <%= f.input :password %>
  <%= f.button :submit %>
<% end %>

尝试根据需要放置所有输入:false 这应该允许跳过simple_form验证,并且数据进入控制器,并且可以对模型进行过滤或/和验证,以及在持久化之前要执行的所有其他操作。

在模型类中,可以使用几种验证方式,例如:

您还可以使用:if和:unless选项,并在符号上使用与方法名称相对应的符号,该名称将在验证发生之前立即被调用。 这是最常用的选项。

例如

class Participant < ApplicationRecord
   belongs_to :study

   validates :name, presence: true
   validates :company, presence: true
   validates :time_zone, presence: true
   validates :mobile_number, presence: true if: :channel_is_sms? 
   validates :email, presence: true if: :channel_is_email? 

  def channel_is_sms?
    channel == "sms"
  end

  def channel_is_email?
    channel == "email"
  end
end

或者,您也可以在所有需要验证的地方使用自定义验证器 例如

class MyValidator < ActiveModel::Validator
  def validate(record)
    unless record.channel == 'sms'
      ...
      ...  actions here
      ...
    end
  end
end

class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM