0

我不知道为什么这两段代码在 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。

任何想法?谢谢!

4

3 回答 3

5

您的代码的解析顺序有问题。变量在使用前需要定义。

即使在if语句子句中定义的变量“泄漏”到当前范围内,它们也不会在 Ruby 代码中“向后”泄漏。

Ruby 有点好奇,因为需要在解析器解析代码之前定义变量。解析是从上到下,从左到右进行的。

因此,由于变量是在您使用它的块代码之后type定义的,因此它在块中将不可用。

例子:

>> 3.times { puts x } if (x = 123)
NameError: undefined local variable or method `x' for main:Object

您没有收到任何错误消息的原因是 Ruby 1.8type中的方法是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从长远来看,它很可能会让您头疼。

于 2013-07-26T08:56:56.310 回答
0

我遇到的类似问题是“类型”是数据库中的关键字,它允许我们的模型将字段设置为“类型”,但它在不同条件下的工作方式很奇怪。如果更改名称是您的一个选项,请在更改名称后检查,对我有用...

于 2013-07-26T08:58:29.053 回答
0

gem Squeelinstance_eval在调用传递给where. @type因此,在 squeel 实例中没有任何内容。如果您想使用来自另一个上下文的方法或变量,请尝试将其包装到my带有块的方法中

orders = Order.where { type.eq my { @type } } if @type.present?

PS对不起我的英语

于 2014-01-29T08:22:15.000 回答