You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails的Array.include?是否仅校验对象引用而非对象内容?

问题解答

首先明确结论:Ruby原生的Array#include?方法默认通过==运算符判断元素是否匹配,普通自定义类的==运算符默认校验对象引用身份(即object_id是否相同),不会主动对比对象的属性值。你遇到的测试失败就是因为expected_bubble和数组中属性一致的Bubble对象是两个不同实例,object_id不同,所以判断为不匹配。

可行解决方案

方案1:重写DTO类的==方法

在Soda::DTO::Bubble类中自定义==的对比规则,指定需要校验的属性:

class Soda::DTO::Bubble
  def ==(other)
    return false unless other.is_a?(self.class)
    container_id == other.container_id &&
    bubble_type == other.bubble_type &&
    flavor_id == other.flavor_id &&
    bubble_sid == other.bubble_sid &&
    id == other.id &&
    desc == other.desc
  end
end

修改后原生Array#include?和RSpec的include匹配器都会按属性对比判断是否匹配。

方案2:使用RSpec属性匹配语法(无需修改业务代码)

不需要修改DTO类定义,直接在测试中用an_object_having_attributes匹配器:

# 直接传入要匹配的属性
expect(bubble_dtos).to include(
  an_object_having_attributes(
    container_id: 594,
    bubble_type: "co2",
    flavor_id: 3528,
    bubble_sid: "soda::bubble:dbid/1421",
    id: 1421,
    desc: "desc3"
  )
)

# 如果已有expected_bubble对象,也可以直接读取它的属性
expect(bubble_dtos).to include(an_object_having_attributes(expected_bubble.attributes))

方案3:转哈希后对比

将所有对象转为属性哈希后再判断是否包含:

expect(bubble_dtos.map(&:attributes)).to include(expected_bubble.attributes)

补充说明

如果你的DTO是通过Ruby的Struct或Data类定义的,它们默认已经实现了按属性对比的==方法,不会出现这类问题,只有普通自定义类默认按引用对比。


内容的提问来源于stack exchange,提问作者HeyThere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:54:04