6

我是 Ruby 新手,最近在创建 Ruby on Rails 应用程序时遇到了与值进行比较的问题。在控制器中,我有以下始终返回 false 的语句:

if (user.id != params[:id])

问题是 user.id(它是一个 Active Record)是一个整数,而 params[:id] 是一个字符串。我花了一段时间才弄清楚这一点,最后我把它改成了:

if (user.id != params[:id].to_i)

现在该语句按预期工作。

为避免将来出现此错误,是否有办法“编译”或让 Ruby 在您尝试比较 2 种不同类型时发出警告?我遇到的其他一些我想“编译检查”的问题是:

  • 如果我创建变量但不使用它,请警告我。帮助检查变量名中的拼写错误。
  • 确保类中存在一个方法,这样我就可以避免方法名称拼写错误,也有助于重构,例如,如果我重命名一个方法。

我目前在 Windows 上使用 Ruby 1.8.6-27 RC2 和 Rails 2.3.2 和 RadRails IDE。

4

6 回答 6

5

先测试,再编码。如果您编写的测试涵盖了应用程序的所有分支,您就可以确保您的代码既能运行又能产生正确的结果。

编辑:我应该指出,比较两种类型的能力,直到最后一秒才依赖方法名称等是 Ruby 的核心特性。

您不会像向对象发送消息那样调用方法。然后该对象负责确定如何处理该方法。在 Rails 中,这用于访问 ActiveRecord 中的 DB 列。在将具有列名称的消息发送到对象之前,没有列的方法。

Ruby 中的静态类型与鸭子类型系统背道而驰。人们通常可以免费获得多态性,而不必担心复杂的继承/接口方案。

我建议采用这些功能并通过测试来弥补不确定性

于 2009-07-09T14:42:08.290 回答
2

Ruby 不允许您为 Object 重新定义 == 运算符。在 ruby​​ 1.8 中你不能,Ruby 1.9 应该这样做,但我无法让我的脚本为核心类工作。它适用于自定义对象。

class Object

  alias :equal_without_warning :==

  def ==(object)
    unless self.class == object.class
      warn("Comparing `#{self.class}' with `#{object.class}'")
    end
    equal_without_warning(object)
  end

end

假设我没有犯一些愚蠢的编码错误,答案是否定的:你无法检查你是否在比较不同类型的对象。

另外,我会说你没有。实际上 Ruby 并非设计为以这种方式工作,这更像是一种 java 方法而不是 Ruby 风格。

于 2009-07-09T16:16:38.333 回答
1

Ruby 不应该是安全的。它可以让您比较任何两个对象,这就是它的大部分功能的来源。如果没有这种动态设计,Rails 就不可能实现。

即使是 Java 或 C 之类的编译语言也不会阻止您对两个对象执行 == 操作。正如本所说,最好先测试。检查您正在使用的结构。获取有关 Ruby 对象的信息的一种方法是使用:

puts object.class
于 2009-07-09T14:47:46.843 回答
1

一般来说,避免动态/脚本语言出现此类问题的最佳方法(我知道)是将“逻辑”移至方法/命令并为它们编写单元测试。基本上,任何可能失败的东西都应该进行测试。页面上的代码应该是愚蠢的逻辑......而不是只显示那些满足特定条件的项目,它应该显示所有项目,并从只返回应该显示的项目的方法中获取项目列表。

于 2009-07-09T14:48:29.837 回答
0

我建议两件事:

一:阅读 IRB(或 rails 的脚本/控制台)。动态语言的一个常见开发实践是在“实时”解释器(如 IRB 或 rails 控制台)中尝试代码片段。这种做法可以追溯到最早的动态语言,如 Smalltalk 和 Lisp。Ruby-debug 对于解决问题也非常有用,并且是找出示例中的错误的一种非常简单的方法。

二:阅读“Duck Typing”。“类型”和变量在 Ruby 中的工作方式与许多人所期望的略有不同。据我了解,像 user.id 这样的变量没有“类型”。user.id指向的值确实有类型,但变量本身没有。我相信这就是为什么没有工具可以在运行程序之前告诉您错误是什么的部分原因。比较这两个变量不是错误,因为变量没有类型。user.id 在你的程序中指向一个整数,但是将 user.id 分配给一个字符串是完全合法的,此时比较会更有意义。:-)

于 2009-07-13T01:33:36.933 回答
0

我发现的最佳解决方案是进行动态语法检查的 IDE,例如 RubyMine。我不确定它是否能解决我最初的问题,但它帮助我找到并修复了其他几个语法和编译错误。谢谢大家的建议。

于 2015-10-26T20:29:27.540 回答