ruby - `detect` 和 `find` 返回 `nil` 而 `find_all` 和 `select` 返回结果
问题描述
使用下面的代码,byebug 会跳闸:
cspg_instance = @game_instances.find do |instance|
instance_end_time = TimeOperation.new(:+, instance.start_time, instance.duration).result
if (event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period)
byebug
end
end
这将返回正确的结果:(编辑:此 WAS 返回正确的结果,现在返回 nil)
cspg_instance = @game_instances.find do |instance|
instance_end_time = TimeOperation.new(:+, instance.start_time, instance.duration).result
if (event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period)
ok = true
end
ok
end
然而,它只返回nil
'if' 条件(没有if
语句);而find_all
两者select
都返回一个值。
cspg_instance = @game_instances.find do |instance|
instance_end_time = TimeOperation.new(:+, instance.start_time, instance.duration).result
(event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period)
end
我想知道是否有人知道该怎么做;也许是红宝石或安装失败?
解决方案
有两个不同的问题:
1)为什么版本byebug
不起作用
这是文档中的重要部分find
:返回第一个不为假的块。
现在让我们看看您的案例:
# just writing "true" here, with no if statement will deliver a result
如果你只是写true
在块的末尾,那么它true
会被返回,因此会find
找到这个条目。
if (event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period)
ok = true
end
ok
这种情况类似:如果if
条件是true
您分配true
给ok
变量。因为您ok
在块的最后一行再次调用,所以块返回true
并find
找到该元素。
if (event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period)
byebug
end
但是你的代码中的这个例子是不同的。bundle
如果if
条件为,则在此处打开true
。这使得bundler
调用成为find
块中的最后一个方法调用。调用bundler
不会返回true
,因此整个块不会返回true
并且find
不会选择这些条目。
true
解决方案是在块的最后一行返回find
。因为您的代码中已经有了条件,所以您可以直接使用它而无需true
先分配给变量。– 例如像这样:
cspg_instance = @game_instances.find do |instance|
instance_end_time = TimeOperation.new(:+, instance.start_time, instance.duration).result
event.end_time > instance.start_time && event.end_time <= instance_end_time && instance.events.first.period == event.period
end
2)为什么find_all
和select
工作,但find
没有?
在评论中,您澄清了@game_instances
它实际上不是一个数组,而是一个ActiveRecord::Relation
. ActiveRecord::Relation#find
工作方式与Array
. find
在这种关系上进行简化,需要id
一个记录,并在关系给定的范围内返回该记录。调用to_a
关系会将所有记录加载到内存中,并允许您使用Array#find
.
从性能的角度来看,将条件转换为 SQL 条件并仅加载从数据库中匹配的一条记录而不是加载所有记录并在应用程序中找到正确的记录是有意义的。
推荐阅读
- python - 在 tkinter 中删除画布生成的图形
- c - 我怎样才能得到我的代理人接下来应该调动的职位?
- ios - 如何在 Swift 中触发具有不同内容的预定通知?
- capl - 使用 CAPL 程序参考 LED 可见性?
- reactjs - onIonChange 事件后选择的选项取消选择
- python - 更新单个数据帧行中的多列的最有效方法
- javascript - Reactjs 将数据从子函数组件发送回父类组件
- c# - 如何在泛型函数方法调用中使用按参数排序
- java - Java hashmap算法检查值
- java - 如何在 java 中修改 HttpServletRequest 正文?