简体   繁体   English

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

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

I have a study that can have participants . 我有可以participantsstudy I have a simple_form where the user can add participants. 我有一个simple_form ,用户可以在其中添加参与者。 It looks a bit like a table: 它看起来有点像一张桌子:

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

By default, the screen has three fieldset rows, and the user can add more rows if needed. 默认情况下,该屏幕具有三个字段集行,并且用户可以根据需要添加更多行。 Each row is one participant. 每行是一个参与者。

I would like my participant model to validate only the rows that have been filled out, and ignore rows that are blank because even though we are showing three by default to the user, not all three are required fields. 我希望我的participant模型仅验证已填写的行,而忽略空白行,因为即使我们默认向用户显示三行,也不是全部都是必填字段。

Here's the relevant portion of app/models/participants.rb . 这是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

In participants_controller.rb I have: participants_controller.rb我有:

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

The problem is that I get an error because simple_form thinks that all three fields are required, and not just the first row. 问题是我得到一个错误,因为simple_form认为所有三个字段都是必需的,而不仅仅是第一行。

Rails' validators accept conditions: 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' }

By default all inputs are required. 默认情况下,所有输入都是必需的。 When the form object includes ActiveModel::Validations (which, for example, happens with Active Record models), fields are required only when there is presence validation. 当表单对象包含ActiveModel :: Validations(例如,在Active Record模型中发生)时,仅当存在状态验证时才需要字段。 Otherwise, Simple Form will mark fields as optional. 否则,“简单表单”会将字段标记为可选。 For performance reasons, this detection is skipped on validations that make use of conditional options, such as :if and :unless. 出于性能原因,在使用条件选项(例如:if和:unless)的验证中将跳过此检测。

And of course, the required property of any input can be overwritten as needed: 当然,可以根据需要覆盖任何输入的必需属性:

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

Try to put all the inputs as required: false . 尝试根据需要放置所有输入:false That should allow skip simple_form validations and the data came into the controller and the model can be filtered or/and validated and every other things you want to do before persist. 这应该允许跳过simple_form验证,并且数据进入控制器,并且可以对模型进行过滤或/和验证,以及在持久化之前要执行的所有其他操作。

In the model class you can use several ways of validations for example: 在模型类中,可以使用几种验证方式,例如:

you also can use the :if and :unless options with a symbol corresponding to the name of a method that will get called right before validation happens. 您还可以使用:if和:unless选项,并在符号上使用与方法名称相对应的符号,该名称将在验证发生之前立即被调用。 This is the most commonly used option. 这是最常用的选项。

for example 例如

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

or also you can use custom validator where you do all that you need validate. 或者,您也可以在所有需要验证的地方使用自定义验证器 for example 例如

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