10

我正在使用 Ruby 1.9.2 和 Ruby on Rails 3.2.2。我有以下方法:

# Note: The 'class_name' parameter is a constant; that is, it is a model class name.
def my_method(class_name)
  case class_name
  when Article then make_a_thing
  when Comment then make_another_thing
  when ...     then ...     
  else raise("Wrong #{class_name}!")
  end  
end

我想了解为什么在case上面的语句中,else当我执行方法调用时,它总是运行“部分” my_method(Article)my_method(Comment)等等。

我该如何解决这个问题?有人建议如何处理这个问题吗?

4

3 回答 3

4

将对象引用传递给该方法,因为在后台它使用 === 运算符,因此这些将失败。例如

obj = 'hello'
case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

另一方面,这工作正常:

obj = 'hello'
case obj  # was case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

请参阅“如何在 Ruby 中编写 switch 语句”的相关答案https://stackoverflow.com/a/5694333/1092644

于 2012-10-23T00:46:00.737 回答
4

这是因为casecalls======on Class(或者特别是 Module,Class 的后代)是这样实现的:

mod === objtruefalse

大小写相等 -true如果obj是 的一个实例mod或其中一个mod后代,则返回。对模块的使用有限,但可用于 case 语句按类对对象进行分类。

这意味着对于除Class& Module(例如Foo)之外的任何常量,Foo === Foo总是返回false。结果,您总是在语句中得到else条件。case

相反,只需调用case对象本身,而不是其类,或使用if语句。

于 2012-10-23T00:51:24.810 回答
1

to_s如果您只想比较名称的相等性,可以添加到类常量。

def my_method(class_name)
  case class_name.to_s
  when 'Article'
    make_a_thing
  when 'Comment'
    make_another_thing

  ... ...

  end  
end
于 2015-12-23T17:30:12.183 回答