Steve Lane
Steve Lane

Reputation: 769

Ruby initialization idiom using symbols

I'm doing some work in an existing Ruby code base, and I'm quite new to Ruby. I see this initialization idiom pretty often:

def initialize(input)
    @number         = input[:number]
    @color          = input[:color]
  end

I guess I have two questions. One is whether this is a common idiom and if so, what's good about it? The second is, what is actually happening here? Is the implication that input is an array? A hash? The underlying mechanics aren't clear to me.

Upvotes: 0

Views: 990

Answers (2)

David Grayson
David Grayson

Reputation: 87486

Yes, it's common. Generally when you see code like this, it means that input is a Hash. Occasionally someone might pass in an object that acts like a hash, though, and we can still expect this code to work. We can tell that input is definitely not an array, because arrays require Integers to be used as their index, but :number and :color are Symbols.

Whenever you see something starting with a colon like :number, that is a Ruby symbol.

Whenever you see something starting with a @ like @number, that is the name of an instance variable. Instance variables are used to store data inside objects for later use.

Suppose we have a class Foo defined like this:

class Foo
  def initialize(input)
    @number = input[:number]
    @color = input[:color]
  end
end

In this case, we can create a new object like this:

Foo.new(number: 4, color: 'red')

The code above is equivalent to:

input_hash = { :number => 4, :color => 'red' }
Foo.new(input_hash)

One nice thing about this pattern is that you can tell exactly what each input variable is being used for because it will be written next to a descriptive symbol, and also it doesn't matter what order you put the input variables in.

Improvements

If you want to improve this code, you might consider using a new feature of Ruby called keyword arguments. Alternatively, you might also consider Hash#fetch so you can have more control over what happens when one of the keys is missing, instead of just storing a nil value in your object. I would also recommend that you check the input hash for any unexpected keys and raise an exception if they are found.

Upvotes: 2

the Tin Man
the Tin Man

Reputation: 160571

Is this a common idiom and if so, what's good about it?

It's not common, but it's acceptable. When there are more than n parameters being passed in, where "n" is often > 3, we should use a hash.

What's good about it? Look at the code. Is it simple and readable? Does it make sense that an input parameter of :number is being assigned to an instance variable of the same name?

what is actually happening here? Is the implication that input is an array? A hash? The underlying mechanics aren't clear to me.

It's a hash where :number and :color are keys.

Upvotes: 1

Related Questions