模型中链接布尔值的验证-Rails 5.2

时间:2019-05-16 13:22:31

标签: ruby-on-rails

我的应用程序在其中一个数据表中有两个链接的布尔字段,这些字段标记了记录可能属于的类别。也就是说,这两个字段可以是truefalse,我要求其中一个(只有一个)为true,以使记录有效。 (万一有人想知道,将来可能会有更多的类别,因此具有单个字段的简单二进制选项将无法使用很长时间,我想解决根本问题。)

因此在我的应用程序中,这些值及其整体有效性的选项为:

field a   |   0   |   1   |   0   |   1
field b   |   0   |   0   |   1   |   1
========================================
valid?    |   N   |   Y   |   Y   |   N

我在模型中进行了以下验证:

  validates :a, presence: true, unless: :b
  validates :b, presence: true, unless: :a

这通过确保至少一个字段为true来捕获某些错误情况。但是,此验证允许两个字段也为真,这是我不希望的。

有什么方法可以在模型中强制执行此最终验证选项(顶部表格的第四列)?

目前,我正在按以下方式创建记录时在控制器中捕获它(强制将“ true true”更改为“ false false”,模型将捕获并拒绝):

    if params[:word][:a] == "1" && params[:word][:b] == "1"
      params[:word][:a] = "0"
      params[:word][:b] = "0"
    end

但是我敢肯定,必须有一种更优雅的方法!

1 个答案:

答案 0 :(得分:0)

您可以尝试像这样的自定义验证器:

       stmt = conn.prepareCall("call clone_ad(?, ?, ?, ?)");
       stmt.setLong(1,1L);
       stmt.setLong(2,1000L);
       stmt.setLong(3,999L);
       stmt.setObject(4,null, Types.BIGINT);
       stmt.registerOutParameter(4, Types.BIGINT);
       boolean hadResults = stmt.execute();

基本上,您需要XOR运算符。

编辑(针对@jvillian的评论):

如果要确保许多布尔值中只有一个真实值,我建议使用.inject进行以下操作:

validate :a_xor_b

...

def a_xor_b
    errors.add(:a_xor_b, "only one must be true") unless a ^ b
end