将类作为参数传递给Ruby

时间:2014-05-23 23:17:38

标签: ruby sinatra

我当前的sinatra路由器看起来像这样但是多个商店正在路上,所以我想用一行代替这个案例,

get_or_post "/list.json" do
  case
    when params[:store]=='storeVakanties' then return jsonp(get_data_for(Vakantie))
    when params[:store]=='storeDeelnemers' then return jsonp(get_data_for(Deelnemer))
    when params[:store]=='storeJobstudenten' then return jsonp(get_data_for(Jobstudent))
  end
end

如果我将我的ExtJs商店重命名为activerecord类的名称,我可以做类似的事情

get_or_post "/list.json" do
  jsonp(get_data_for(params[:store])) #eg params[:store]='Vakantie'
end

但我需要传递一个类,而不是一个字符串..任何建议?

4 个答案:

答案 0 :(得分:2)

在最简单的情况下(没有命名空间),您可以使用:

Object.const_get(params[:store])

如果你需要使命名空间不变,你可以做

params[:store].split('::').inject(Object) {|klass, name| klass.const_get(name) }

要获得更高级的实现,请查看ActiveSupport的Inflector constantize方法的来源:http://apidock.com/rails/v4.0.2/ActiveSupport/Inflector/constantize

答案 1 :(得分:1)

如果你想限制可用的类,这样的东西可以工作:

params = { store: "Vakantie" }

[Vakantie, Deelnemer, Jobstudent].find { |c| c.to_s == params[:store] }
#=> Vakantie

我可能只是编写一个帮助器方法并明确映射这些类:

helpers do
  def store(name)
    case name
    when 'storeVakanties' then Vakantie
    when 'storeDeelnemers' then Deelnemer
    when 'storeJobstudenten' then Jobstudent
    end
  end
end

get_or_post "/list.json" do
  jsonp(get_data_for(store(params[:store])))
end

答案 2 :(得分:0)

您可以使用eval

get_or_post "/list.json" do
  jsonp(get_data_for(eval(params[:store])))
end

如果您对此感到震惊,可以使用const_get

Kernel.const_get(params[:store])

但是,您需要执行一些验证,因为允许用户输入选择任何已定义的类是危险的。

答案 3 :(得分:0)

我自己使用ActiveSupport的constantize

找到了解决方案
jsonp(get_data_for(params[:store].constantize))

在我的情况下,安全性不是问题,但我最喜欢Stefan的解决方案,所以我给了他信用。