Ruby passing symbol(s) as keyword argument(s)?

Viewed 152

I have a method, where I want to use keyword parameter(s) and case/when statements, where I prefered to use symbols:

  def navigate_to(page:)
    case page
    when :inbox
      # some code
    when :archive
      # some code
    else
      # some code
    end
  end

Is this the correct syntax when calling the method?

navigate_to page: :inbox

The : : seems a little bit strange.

2 Answers

The keyword argument syntax is:

key: value

If key is page and value is the symbol :inbox, you indeed have:

page: :inbox

You could also use a positional argument instead:

def navigate_to(page)
  # same as your code
end

navigate_to :inbox

Yes, the correct syntax is navigate_to page: :inbox.

While this is common Ruby, it is short and equivalent for several different things. First, the braces.

You are actually calling:

navigate_to(page: :inbox)

Second, the keyword argument pattern originates from hashes as arguments. Before there were keyword arguments, a common way would be to pass in a hash[1], like so:

def navigate_to(options)
  page = options[:page]
end
navigate_to({ page: :inbox })

But when last argument in a method call is a hash, one can leave out the {}.

And last, the actual keys in the hash. A while ago (1.8 -> 1.9 IIRC) a short version was introduced for the following:

{ :page => 'Some Value' }, namely { page: 'Some Value' }. When Some Value is a symbol, that becomes { page: :inbox }.

So, taking all that:

navigate_to page: :inbox

Orignates from:

navigate_to({ :page => :inbox })

It might make more sense reading it like this, or knowing it comes from that.

And I know Ruby, nor ruby-ist, like braces, (), as can be seen in the mindboggling DSL of for example rspec, but I can advise especially new developers, to add them. It often makes code better understandable.

navigate_to(page: :inbox) is probably easier to understand than navigate_to page: :inbox, especially when you start calling through other methods: navigate_to page page_from_session :user.


[1] But, to stress, that is not really what is happening here. Keyword arguments and hash arguments do differ, now that we have keyword arguments. this just shows why the syntax is this way.

Related