我不知道为什么这两段代码在Ruby 1.8.7中表现不同,因为一个似乎是另一个的单行版本。
第一段代码(它可以正常工作):
if @type.present?
type = @type
orders = Order.where{type.eq(type)}
end
单行版本(根本不起作用,没有错误,但似乎也没有执行):
orders = Order.where{type.eq(type)} if (type = @type).present?
注意:我正在使用squeel gem,这就是块跟随where方法的原因。此外,变量类型必须捕获实例变量@type,因为执行上下文在块内部发生更改,并且实例变量不在主上下文和块上下文之间共享。
注2:由于遗留原因,我必须使用Ruby 1.8.7。
有什么想法吗?谢谢!
答案 0 :(得分:5)
解析代码的顺序有问题。变量在使用前需要定义。
即使在if
语句子句中定义的变量“泄漏”到当前范围内,它们也不会在Ruby代码中“向后”泄漏。
Ruby有点好奇,需要在解析器解析代码之前定义变量。解析从上到下,从左到右完成。
因此,变量type
在您使用它的块代码后定义,它将无法在块中使用。
示例:
>> 3.times { puts x } if (x = 123)
NameError: undefined local variable or method `x' for main:Object
您没有收到任何错误消息的原因是Ruby 1.8 type
中的方法是Object#class
的同义词。
所以你的代码真正做的是(可能):
orders = Order.where{type.eq(this.class)} if (type = @type).present?
要修复它,您必须在使用之前定义type
。因此,除非你只是这样做,否则你不能把它变成单行:
orders = Order.where{type.eq(@type)} if @type.present?
总而言之,在Ruby 1.8中使用type
作为Rails模型中的变量并不是一个好主意,因为Object#class
问题从长远来看很可能会给您带来麻烦。
答案 1 :(得分:0)
我得到的类似问题是'type'是数据库中的关键字,它允许我们的模型将字段设置为'type',但它在不同条件下工作奇怪。如果更改名称是您的选项,请在更改后检查,为我工作......
答案 2 :(得分:0)
gem Squeel在传递给instance_eval
的调用块时使用where
方法。因此,在squeel实例中没有任何@type
。如果要使用其他上下文中的方法或变量,请尝试将其包含在带有块
my
中
orders = Order.where { type.eq my { @type } } if @type.present?
对不起我的英文