假设我有对象 my_obj
我从数据库中获取此对象,进行更多计算,无所谓......
然后我需要通过这样的对象进行迭代,例如:
my_obj.each do |m|
some_method(m.id)
end
这段代码不好,因为如果my_obj为nil,我会得到如下错误:
undefined method `each' for nil:NilClass
所以我决定写:
if my_obj.present?
my_obj.each do |m|
some_method(m.id)
end
end
但我认为还有另外一种方法可以做到这一点,如果构建的话,无需写到处。
所以我怎么能通过对象迭代,只有它不是null?
答案 0 :(得分:5)
我发现代码对于正常的OOP原则有点反模式“告诉,不要问”。我在控制台中尝试了这个问题,发现你的担心是不必要的。
无论结果是什么,空白数组或空白的ActiveRecord :: Relation对象,each
都可以工作并返回一个空白数组[]
。
Article.count
# => 0
articles = Article.all # Return array in Rails 3
articles.each { |a| puts a.title }
# => []
articles = Article.scoped # Return ActiveRecord::Relation object in Rails 3
articles.each { |a| puts a.title }
# => []
我建议您查看方法并返回查询结果。如果您的查询返回异常情况,请确保它至少返回一个空白数组。那你就不需要考虑太多。
答案 1 :(得分:5)
最简单的处理方法是使用'Array'转换函数来包围对象,该函数会将您可能的nil输入强制转换为数组,同时保持现有数组不受影响,例如
>> Array(nil)
=> []
和
>> Array([1])
=> [1]
所以在你的情况下:
Array(my_obj).each do |m|
some_method(m.id)
end
答案 2 :(得分:3)
集合查询应始终返回可迭代对象,但有几种方法。 nil
检查的问题导致了一个名为NullObjects的模式,这通常是最好的解决方案。除此之外,你可以做到:
my_object.to_a.each do |m|
some_method(m.id)
end
或
my_object.try(:each) do |m|
some_method(m.id)
end
或
(my_object || []).each do |m|
some_method(m.id)
end
答案 3 :(得分:2)
在Rails中,您可以执行Object#try
方法:
my_object.try(:each) do |m|
some_method(m.id)
end
如果each
不是my_object
,它会使用附加块调用nil
(返回其结果)。否则,它将不会调用each
方法并返回nil
。
答案 4 :(得分:2)
你可以像这样初始化;
def fields_each(fields)
if fields.present? && fields.keys.present?
fields.each do |key, value|
yield(key, value) if block_given?
end
end
end
和用法;
fields_each({a: 1, b: 2, c: 3}) do |key, value|
puts "Key: #{key} value: #{value}"
end
答案 5 :(得分:1)
每个人都忘记了真棒[my_objects].flatten.compact
!
答案 6 :(得分:1)
在经过2.4.1
测试的较新的红宝石版本中,可以写为
my_obj&.each do |m|
some_method(m.id)
end
答案 7 :(得分:0)
初始化my_obj
时,请执行此操作
my_obj = Model.all || [] # Empty array will not iterate or throw error
<强>实施例强>
[].each do |x|
p "I will not execute"
end
答案 8 :(得分:0)
你可以在循环上面试试这个:
if my_obj == nil then
redirect_to "something_else"
end