Ruby way to initialize an object

I am trying to figure out the best way to initialize an object. We can either pass an object, hashes, or variables through the initialize method. However, what are the consequences of passing an object vs a hash?

I heard that the best way to use a hash and pass it as a parameter but the ability to modify the object also disappears unless we retrieve that object. So far, I have this as my initialize method:

def initialize(args)

      args.each do |k,v|
        instance_variable_set("@#{k}", v) unless v.nil?
      end
end

Any suggestion?

Your example implies that you don’t know what arguments you want to pass in, or that the list is so long that you don’t want to intialise each one.

If you do know which arguments you want, and using ruby 2.0 you can use named arguments:

def initialize(awesome_arg: nil, name: "")
  @awesome_arg = awesome_arg
  @name = name
end

If you prefer to go with meta programming, you can do:

def initialize(args = {})
  args.each do |attr_name, attr_value|
    public_send("#{attr_name}=", attr_value)
  end
end

By using public_send you make sure you only use setters that are public, and by using the setter you make sure that any operations done by setter to the value are also done on the initialiser.

That being said, if you don’t want to use the setter, you can do what you are already doing, no need to check if the value is nil, though. You might want to initialise a variable to nil, or access it afterwards and check if it is nil.

Thanks for the quick reply @zamith. You are correct, the list is so long that I don’t want to initialize each one. I actually use attr_required to make sure some attributes are set. I will look into public_send method. I have been using send method this whole time so public_send seems like the way to go.

Can it be harmful if I pass objects as the parameters? I keep on getting stack too deep whenever I run my tests. In the learn repo, I noticed that some initialize method takes in objects instead of named arguments/hashes. Is it harmful if I passed in two or three objects as arguments?

Thanks for everyone’s help and input!

There should be no problem is passing objects as parameters, since hashes, ints, strings, etc, are also objects in ruby.

Thanks! Perhaps it is how I designed my app or RSpec. I am not sure why I am getting the stack too deep issue.

Probably there’s some recursion happening that you’re unaware of. Maybe if you post your code we can take a look.