寻找具有字符串的更好的逻辑XOR解决方案

时间:2011-09-10 05:41:13

标签: ruby-on-rails ruby

我正在编写一些代码来评估一堆字符串的存在,我想确保只有1存在。它们是相互排斥的。

class MyClass
  include ActiveModel::Validations
  attr_accessor :a, :b, :c
  validate :mutex_values 

  def initialize(attr = {}) 
    attr.each do |k, v| 
      send("#{k}=", v)
    end 
  end 

  private 
  def mutex_values 
    # here, I want to do this:
    # errors.add(:base, "specify only 1") unless a ^ b ^ c
    # instead I do this
    errors.add(:base, "specify only 1") unless a.present? ^ b.present? ^ c.present?
  end
end 
MyClass.new(:a => "A", :b => "B", :c => "C").valid? 
=> false

是否有其他方法不需要重复使用.present?? Monkey patch用于定义运算符^的字符串?我只是习惯于能够做if a,因为需要基本上对布尔值的显式转换感觉不自然。我觉得这个用例会在Ruby中“正常工作”。

3 个答案:

答案 0 :(得分:2)

您可以使用count执行此类操作:

errors.add(:base 'specify exactly 1') unless [a, b, c].count(&:present?) == 1

如果您最多想要一个而不是一个,那么:

errors.add(:base 'specify at most 1') unless [a, b, c].count(&:present?) > 1

例如:

> ['',nil,'6',''].count(&:present?)
=> 1 
> ['',nil,'6',11].count(&:present?)
=> 2 
> ['',nil,''].count(&:present?)
=> 0 

答案 1 :(得分:2)

Enumerable实际上定义了一个one?方法,它完全符合您的需要。

# So either...

[a, b, c].one?(&:present?)

# or

[a, b, c].one?(&:presence)

# ... would do the trick in this case.

不幸的是,如果你想要two?或etcera,那你就不走运了。

答案 2 :(得分:1)

如果您想检查方法abc中是否只有一个返回非空值,您可以使用:

[a, b, c].compact.count == 1

或者甚至,多亏了数字,

[a, b, c].one?