为什么 uniq return 在另一个对象中使用时会出现不合逻辑的答案?

Why does uniq return an illogical answer when used inside another object?

感谢您的宝贵时间。我的 RSpec 规范中有一个有趣的逻辑错误。下面我提供了两个例子,第一个总是失败而第二个通过。

例如:下面的代码将创建一个期望 3 但返回 1 的失败规范

it "must not have the same question twice" do
  exam = Exam.new
  q1 = Question.new(question: "What color is the sky?")
  q2 = Question.new(question: "What color is the sky?")
  q3 = Question.new(question: "What sound does a dog make?")
  q4 = Question.new(question: "What sound does a dog make?")
  q5 = Question.new(question: "hello world?")
  exam.questions.push(q1,q2,q3,q4,q5)
  expect(exam.questions.uniq.size).to eql(3)
end

然而,当我使用下面的内容时,用常规数组替换考试对象时,它按预期工作并通过了规范。

it "must not have the same question twice" do
  exam = []
  q1 = Question.new(question: "What color is the sky?")
  q2 = Question.new(question: "What color is the sky?")
  q3 = Question.new(question: "What sound does a dog make?")
  q4 = Question.new(question: "What sound does a dog make?")
  q5 = Question.new(question: "hello world?")
  exam.push(q1,q2,q3,q4,q5)
  expect(exam.uniq.size).to eql(3)
end

这是我在问题对象中覆盖方法的示例

def ==(other)
  question == other.question
end

def eql?(other)
  other.is_a?(self.class) && question.eql?(other.question)
end

def hash
  question.hash
end

exam.questions.uniq 正在删除 ActiveRecord::Associations::CollectionProxy.

的重复项

exam.uniq 正在删除数组的重复项。

如果您查看 ActiveRecord source,您会发现记录 ID 用于确定唯一性而不是相等性。

  def distinct
    seen = {}
    load_target.find_all do |record|
      seen[record.id] = true unless seen.key?(record.id)
    end
  end
  alias uniq distinct