Initialize with multiple instance variables as passed array/hash elements

Hey there,

This is what I am trying to achieve;

I would like to create an object with multiple instance variables (passed as an array) and initialize.

here is my initializer;

...    
        attr_accessor :fn

        def initialize(*fn)
          @fn = fn
        end
...

loaded_file = YAML.load_file('example.yml')
fo = MyClass.new(file_load.values.map(&:to_s))
fo.some_method

However in this approach my instance variable is created only once and gets;

["[\"first_instance_var\", \"second_instance_var\", \"third_instance_var\"]"]

My example.yml looks like this;

filename:
  - first_instance_var
  - second_instance_var
  - third_instance_var

My point is to get something like;

["first_instance_var", "second_instance_var", "third_instance_var"]

So that I can iterate with instance methods for each item.

Thanks in advance,

Found the workaround as below;

  file_payload = YAML.load_file('./example.yml')

  file_payload.values.flatten.map do |v|
    pay = MyConfig.new(v)
    pay.my_method1
    pay.my_method2
  end

Please let me know if you have a nicer approach.

Thanks.

Hello

Your variable (file_payload) contain a Hash. You should access the list of the file by asking the key directly:

list_of_files = loaded_file["filename"]

If you need to see the content, just add a line with puts list_of_files.inspect. You can add the couple puts + inspect method to see how your objects are built.

I see you use a splat operator (*) in the arguments of your constructor.

A splat operator is generally used with other positional arguments to tell Ruby we can have 0 to n extra arguments to catch in an Array. I’ve never see a splat operator used alone as you do.

I’m not sure it’s your use-case.

You should use positional argument in your constructor (without splat):

  def initialize(fn)
    @fn = fn
  end

And you can pass now the Array when initialize the class:

MyClass.new(list_of_files)

If you really want to use a splat operator in the argument of your constructor, you have to explode the array while passed to the new method:

MyClass.new(*list_of_files)

Is the same as

MyClass.new(list_of_files[0], list_of_files[1], list_of_files[2])

But you should really don’t use a splat operator without real need. Here, you are out of the use-case for it.

I hope this will help you.

Happy hack.

1 Like

Thanks, @Ludovic ,

This answers my issue and many thanks for the splat operator usage.

Peace!