我的应用程序在其中一个数据表中有两个链接的布尔字段,这些字段标记了记录可能属于的类别。也就是说,这两个字段可以是true
或false
,我要求其中一个(只有一个)为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
但是我敢肯定,必须有一种更优雅的方法!
答案 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