0

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?

1
  • 1
    look up the builder pattern, that's better than doing dynamic methods here. Commented Nov 5, 2018 at 16:12

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.