Pol0nium
Pol0nium

Reputation: 1376

Ruby empty parameter in function

I'm trying to enqueue various functions in a generic way with this code :

{ Object.const_get(object_name).new(job[:params]||={}).delay(:queue => queue).send(method_name)}

job is a Hash where I get the name, objects parameters etc...

My problem is in this case :

class Foo
  def initialize
    puts 'bar'
  end
end

Foo doesn't take parameters for its instanciation.

So if I use the previous line with Foo as object_name I'll get this error :

ArgumentError: wrong number pf arguments (1 for 0)

And I absolutly don't want to write something like that :

if job.has_key?[:param] then
  Object.const_get(object_name).new(job[:params]||={}).delay(:queue => queue).send(method_name)
else
  Object.const_get(object_name).new().delay(:queue => queue).send(method_name)
end

What could I write instead of job[:params]||={} so it works for every case?

Thanks in advance.

Upvotes: 0

Views: 1633

Answers (3)

7stud
7stud

Reputation: 48599

Based on your example, I think the test you accepted might be wrong. Your code suggests that you shouldn't be testing whether the :params key exists in the hash, you should be testing whether initialize takes an argument. If initialize does take an argument, then you send it an argument regardless of whether the :params key exists in the hash. The accepted answer will fail when the :params key doesn't exist in the hash, and yet the initialize method takes an argument--you'll get a 0 for 1 error. Is that a possibility?

class Dog
  def initialize(params)
    p params
    puts "dog"
  end
end

class Cat
  def initialize
    puts "cat"
  end
end

class_names = ["Dog", "Cat"]

job = {
  params: {a: 1, b: 2, c: 3}
}

class_names.each do |class_name|
  class_obj = Object.const_get(class_name)

  if class_obj.instance_method(:initialize).arity == 0
    send_args = 'new'
  else
    send_args = 'new', job[:params] ||= {}
  end

  class_obj.send(*send_args)
end

--output:--
{:a=>1, :b=>2, :c=>3}
dog
cat

Upvotes: 0

akonsu
akonsu

Reputation: 29556

you can achieve this with using Foo.send and using an array.

For instance

Object.
  const_get(object_name).
  send(*(job.has_key?(:param) ? ['new', job[:param]] : ['new']))...

I personally think it is not worth it and an if statement is easier on the eyes.

Upvotes: 1

MurifoX
MurifoX

Reputation: 15089

The initialize method of your Foo class should receive a parameter with a default value. Like this:

class Foo
  def initialize(params={})
    # Here you do stuff like checking if params is empty or whatever.
  end
end

This way you will achieve the two behaviors.

Upvotes: 1

Related Questions