簡體   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