Reputation: 3552
I seem to be having problems with using a hash parameter to my constructor in Ruby 1.9.2. I note that what I'm trying to do works in 1.8.7. Here is my example code:
def initialize(*params)
@attr1 = params[:attr1] or nil
@attr2 = params[:attr2] or nil
end
However, when I try to instantiate an object of this example class, I get an error message on the line where the first instance variable is set: in '[]': can't convert Symbol into Integer (TypeError)
Why does this not work in 1.9.2? And how do I work around it?
Upvotes: 2
Views: 1034
Reputation: 18203
You don't need the splat (*
) to capture a single hash argument. It's used to capture an unknown number of arguments. Change your function definition to
def initialize(params = {})
@attr1 = params[:attr1] or nil
@attr2 = params[:attr2] or nil
end
and everything should work the way you'd expect. Edit: The params = {}
makes the params argument optional, and sets it to an empty hash when nothing is provided.
What's actually being captured in params
with the function definion you have now, would be like this:
Whatever.new(:foo => 'foo', :bar => 'bar')
# params contains [{:foo => 'foo', :bar => 'bar'}]
so you'd need to reach into the array first to get the hash, then use the hash keys.
When Ruby sees a set of hash key/value pairs as the last argument to a function, it's automatically wrapped into a Hash. So even though it looks like you're supplying multiple arguments to the function, the interpreter is actually only receiving a single argument.
Upvotes: 5
Reputation: 8710
Because from splat *
symbol you turn your hash actual parameter into array:
class Test
def initialize(*params)
p params
end
end
Test.new(attr1: 1, attr2: 2) # => [{:attr1=>1, :attr2=>2}]
Remove *
from initialize
method:
class Test
def initialize(params)
@attr1 = params[:attr1] or nil
@attr2 = params[:attr2] or nil
end
attr_accessor :attr1, :attr2
end
test = Test.new(attr1: 1, attr2: 2)
test.attr1 #= > 1
Upvotes: 5