0

I found this interesting answer :

https://stackoverflow.com/a/2348854/169277

This is ok when you're trying to set instance variables it works really great.

Is there a way to apply the same logic or better one to create generic constructor like :

def initialize(obj)
  obj.each do |k,v|
   #find the setter for each k and set the value v to and return newly created object
  end
end

If I had object TestObject:

class TestObject
attr_accessor :name, :surname, :sex
end

I was thinking to create it something like this:

TestObject.new({:name => 'Joe', :surname => 'Satriani'})

How would one achieve this?

So doing this would be a shorthand of :

t = TestObject.new
t.name = 'Joe'
t.surname = 'Satriani'

3 Answers 3

1

Sure, you can use send to send arbitrary messages to an object. Since we're operating on self here, we can just invoke send directly.

def initialize(obj)
  obj.each do |k,v|
    send(:"#{k}=", v)
  end
end

For example, TestObject.new({:name => 'Joe'}) will call send "name=", "Joe".

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

4 Comments

You were missing do after each (I edited), otherwise answer what I was looking for. thanks
Sorry, I just copied the block out of the initial question. :)
good point thanks, it's so much easier to judge other people haha
You don't need the colon.
1

You can inherit from Struct to make a simple object, and then pass in the attributes to the initializer:

class TestObject < Struct.new(:name, :surname, :sex)
end

TestObject.new('Joe', 'Satriani') #=> sex will be nil

You can use OpenStruct to make quick value objects with arbitrary attributes:

t = OpenStruct(name: 'Joe', surname: 'Satriani')

You can include a module like Virtus: https://github.com/solnic/virtus

Or you can do what Chris Heald said.

Comments

0

I think it would be better to use keyword arguments for this. After all, the Hash keys are guaranteed to be valid Ruby identifier Symbols since they need to match up with method names. You don't need the capability to pass in arbitrary Ruby objects as keys of the Hash.

def initialize(**attrs)
  attrs.each do |attr, value| send(:"#{attr}=", value) end
end

TestObject.new(name: 'Joe', surname: 'Satriani')

2 Comments

I am familiar-ed with *attrs but what does it means **attrs ?
@Priti: It's the same but for keyword arguments. It collects all superfluous keyword arguments into a Hash, just like * collects all superfluous positional arguments into an Array.

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.