2016-09-08 75 views
0

我有一个study可以有participants。我有一个simple_form用户可以添加参与者。它看起来有点像一个表:如何在Ruby on Rails模型中进行条件验证?

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 

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

回答

1

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

和当然,任何输入所需的属性可以被覆盖 需要:

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

尽量把所有的投入为要求:假。这应该允许跳过simple_form验证,并且数据进入控制器,模型可以被过滤或/和验证,以及在持续之前您想要执行的其他任何事情。

在模型类,你可以使用验证的几种方法,例如:

,你也可以使用:if和:除非使用方法的名称会马上叫选项与符号在验证发生之前。这是最常用的选项。

例如

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 
+0

谢谢!对于你的第一点,我尝试在simple_form文档后面通过'required:false'作为默认表单,但是无法使其工作。在每个输入上加上'required:false'这个技巧。 –

+0

我还发现,在这种情况下,只有一种方法可以检查它是否是短信,然后使用'unless'作为电子邮件验证程序。例如'如果短信?和'除非是短信?'在移动字段和电子邮件字段验证器行末尾。 –

2

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' } 
+0

谢谢。你能解释一下Proc.new吗?我能不能只说'if:self.channel =='sms''吗? –

+0

嗯,这是行不通的,我想我不清楚 - 研究有一个渠道,而不是参与者。我认为你的答案目前正在寻找参与者。信道,因此p。 –

+0

只是改变条件使用'p.study.channel' – spickermann