Ravi
Ravi

Reputation: 221

Ruby: define method with args

I'm trying to refactor the code by defining the method dynamically with args. I've tried to use Define_method but it's throwing an error and I've been forced to define define_singleton_method.

Here is my code, I want to remove all the methods with call_* prefix.

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

Is there a way I can define call_radio and call_pan methods dynamically?

Upvotes: 0

Views: 84

Answers (2)

Ravi
Ravi

Reputation: 221

I think eval is the better choice to write less code

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

Upvotes: 0

tadman
tadman

Reputation: 211540

case (type) is often a strong sign you need to create subclasses instead of having an omniclass that just pretends to be different classes.

For example:

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

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

Then you just instantiate the right class and the right method gets called.

This is one of the principles of object-oriented design where you specialize classes where appropriate instead of having an unespecialized class that does many different, often contradictory things.

You could do some trickery with method_missing or by calling define_method but that's a lot of work compared to defining a subclass in this case.

Upvotes: 3

Related Questions