如何使用多态来删除比较字符串的switch语句?

时间:2016-04-28 11:09:38

标签: ruby json reflection polymorphism

我是Ruby的新手,所以让我先描述一下我的问题的背景: 我有一个json作为输入,它具有以下键/值对:

{
 "service": "update"
}

该值有许多不同的值,例如:insert,delete等。 接下来有一个方法x来处理不同的请求:

def x(input)

  case input[:service]      
  services = GenericService.new

  when "update"
    result = services.service(UpdateService.new,input)
  when "insert"
    result = services.service(InsertService.new,input)
  when "delete"
    result = services.service(DeleteService.new,input)
  ....
  ....
  else
    raise "Unknown service"
  end
  puts JSON.pretty_generate(result)    
end

困扰我的是我仍然需要使用switch语句来检查String值(让我想起'ugh的实例......)。有更清洁的方式(不需要使用开关)?

最后,我尝试搜索我的问题的答案,但没有成功,如果我错过了,请随时评论相关问题。

更新:我想将字符串转换为相关的类名,如下所示:How do I create a class instance from a string name in ruby?然后调用result = services.services(x.constantize.new,input) ,然后课程的类名需要匹配json的输入。

3 个答案:

答案 0 :(得分:3)

您可以尝试以下内容:

def x(input)

  service_class_name = "#{input[:service].capitalize}Service"
  service_class = Kernel.const_get(service_class_name)
  service_class.new(input).process

end

此外,您可能想要检查这是否是一个有效的服务类名称。

我不明白为什么要将服务传递给GenericService这看起来很奇怪。让服务做它的工作。

答案 1 :(得分:1)

如果你试图通过它的名称来实现一个类,你实际上是在谈论反思而不是多态。

在Ruby中,你可以通过这种方式实现这一目标:

byName = Object.const_get('YourClassName')

或者如果你在Rails应用程序中

byName= 'YourClassName'.constantize

希望这有帮助

答案 2 :(得分:0)

只是初步想法,但你可以这样做:

eval(services.service("#{input[:service].capitalize}Service.new, #{input})") if valid_service? input[:service]

def valid_service?
    w%(delete update insert).include? input[:service]
end

人们无疑会大喊大叫,需要大量使用eval