具有随机参数计数的Ruby调用构造函数

时间:2011-04-06 11:27:45

标签: ruby

我有一些像

这样的课程
class Demo1 < Struct.new(:text, :text2) 
end
class Demo2 < Struct.new(:text, :text2, :text3) 
end

如果我只有名称和参数哈希,我如何调用每个类的构造函数 我需要写这样的方法, 但这是错误的,因为发送后(:new,args)Struct将包含:等于args的文本

 def call_demo_object(demo_name, args={})
          demo_name.to_s.constantize.send(:new,args) 
  end

mian问题是使用hash

中的随机参数调用构造函数

3 个答案:

答案 0 :(得分:3)

变体一:

def call_demo_object(demo_name, args={})
  z = [':new']
  args.keys.each do |key|
    z.push "args[:"+key.to_s+"]"
  end
  eval('demo_name.to_s.constantize.send(' + z.join(', ') +')' )
end

变体二:

def call_demo_object(demo_name, args={})
  a = demo_name.to_s.constantize.send(:new)
    args.each do |key, value|
      a[key] = value if a.members.include?(key)
    end
  a
end

答案 1 :(得分:2)

一种可能的变体:

def call_demo_object(demo_name, args={})
  obj = demo_name.new
  obj.members.each do |member|
    obj[member] = args[member]
  end
  obj
end

这是优点:

  • args可以按任何顺序
  • 仅指定可用的结构成员

答案 2 :(得分:1)

我看到了一些错误:

不确定您的课程是否真的如此,但您最后需要end,否则会出现语法错误。

另外,constantize不是Ruby中字符串的方法,而是Rails定义的方法。所以你需要使用

Kernel.const_get(demo_name.to_s)

获得相同的功能。

正如评论中所指出的,我忽略了如何扩展参数。

要做到这一点,你需要使用所谓的“splat operator”

Kernel.const_get(demo_name.to_s).send(:new,*args) #notice the * in front of args

这将扩大args。

然而,当args是一个哈希值时,比如说{:text=>"hello", :text2=>"hello2"},它会将它扩展为一个包含2个元素的数组,其中每个元素都是一个数组,它们键在第一个位置,键在第二个位置。< / p>

相反,如果您按顺序将对象传递给args,那么您将获得所需的内容。

我认为,如果您要使用的是命名参数,您可能需要尝试其他路线,但我肯定不知道。

要使用可选参数或命名参数,您可以查看Rails如何执行此操作:对参数使用哈希,然后使用键传入哈希。然后,您可以保留有效的密钥列表并检查传入的哈希,并拒绝它们或引发错误。