Ruby:使用args定义方法

时间:2018-11-05 15:46:05

标签: ruby metaprogramming

我正在尝试通过使用args动态定义方法来重构代码。我尝试使用Define_method,但是它抛出一个错误,并且我不得不定义define_singleton_method。

这是我的代码,我想删除所有带有call_ *前缀的方法。

def construct_payload(id, file_name, type)
    case type
    when 'Radio' then call_radio(id, file_name)
    when 'Pan' then call_pan(id, file_name)
    end
  end


  def call_radio(_id, _file_name)
    base(_id).merge(radio(_file_name))
  end

  def call_pan(_id, _file_name)
    base(_id).merge(pan(_file_name))
  end

  def base(_id)
    {
      "id": _id,
    }
  end

 def radio(file)
   { 
      "mode": "ds",
      "file": file
    }
 end

 def pan(file)
   { 
      "mode": "pr",
      "file": file
    }
 end

#enter code here

是否可以动态定义call_radiocall_pan方法?

2 个答案:

答案 0 :(得分:3)

case (type)通常是一个强烈的信号,您需要创建子类,而不是拥有一个伪装成不同类的全能类。

例如:

class Radio < BaseClass
  def call(id, _file_name)
    # ...
  end
end

class Pan < BaseClass
  def call(id, _file_name)
    # ...
  end
end

然后,您只需实例化正确的类并调用正确的方法即可。

这是面向对象设计的原则之一,您可以在适当的地方专门化类,而不要使用非专业的类来处理许多不同的,通常是矛盾的事情。

您可以使用method_missing或通过调用define_method进行一些技巧,但是与在这种情况下定义子类相比,这需要大量的工作。

答案 1 :(得分:0)

我认为eval是编写更少代码的更好选择

def construct_payload(id, file_name, type)
  eval("base(id).merge(#{type}(file_name))")
end

def base(_id)
    {
      "id": _id,
    }
  end

 def radio(file)
   { 
      "mode": "ds",
      "file": file
    }
 end

 def pan(file)
   { 
      "mode": "pr",
      "file": file
    }
 end