如何用nil字段覆盖红宝石中的相等?

时间:2013-06-03 02:42:37

标签: ruby

我不确定如何通过以下测试用例。我使用union for union(|)和inside list.include?(source)

 class Source
  # mongoid object code...
  def hash
    url.hash
  end

  def ==(other)
    eql?(other)
  end

  def eql?(other_source)
    url = self.url and other_source and url == other_source.url
  end
end

测试用例:

  ext1 = Source.new
  ext2 = Source.new(url: "test")

  (ext2.== ext1).should               == false # false
  (ext1.== ext2).should               == false # is returning nil instead of false

我想让最后一个案例返回false而不是nil,但我不确定如何实现这一点?

4 个答案:

答案 0 :(得分:1)

这种常见的模式是“双击”表达式:

!!(url = self.url && other_source && url == other_source.url)

这会将任何值强制转移到truefalse

(另外,the Ruby style guide建议使用&&||代替andor

答案 1 :(得分:1)

当我运行你的代码并点击

  ext2 = Source.new(url: "test")

我得ArgumentError: wrong number of arguments(1 for 0),所以我不确定这是否有用,但也许你的意思

  def eql?(other_source)
    url == self.url and other_source and url == other_source.url
  end

答案 2 :(得分:1)

为什么要使用url变量?

# if they need to be the same class to be equal
def eql(other_source)
  Source === other_source && other_source.url == self.url
end

# OR, if it just matters that it responds to url
def eql(other_source)
  other_source.respond_to?(:url) && other_source.url == self.url
end

请注意,仅测试other_source的真实性不会阻止异常,如果它是真实的并且仍然没有url属性,那么如果您说的话,您当前的解决方案会引发异常,例如{ {1}}

这并不是说在您的示例中,ext1 == true永远不会ext1 任何,因为您正在测试的第一件事是eql的存在1}}。这是你想要的吗?如果这是标准,那么至少有两个没有self.url的来源被认为是平等的吗?

答案 3 :(得分:0)

我不确定您是否忘记粘贴部分代码,但我认为您的意思是这样的:

class Source
  attr_reader :url

  def initialize(params = {})
    @url = params[:url]
  end

  def hash
    @url.hash
  end

  def ==(other)
    eql?(other)
  end

  def eql?(other_source)
    other_source && @url == other_source.url
  end
end

在解决其他问题时解决了您的问题:

  1. 您需要一个名为url的实例变量和一个getter。
  2. 您需要initialize方法。
  3. eql?然后只需要确保other_source不是nil并且比较url s:

    ext2.== ext1 # => false
    ext1.== ext2 # => false