Forum: Ruby question about passing hashes to an action

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
73c04e9ef9ca435c5b19a2e765ae6d20?d=identicon&s=25 Max Williams (max-williams)
on 2007-07-11 21:53
It seems to be a common tactic in ruby to pash what looks like a
key-value pair, in which the key is a symbol, to an action.  For example
with the rails action 'render', we say

render :text => "Hello world!"  #(from dhh's famous blog tutorial)

Can anyone explain to me what's happening here, ie what's being passed
in?  Is it the equivalent of having a (say) java method that takes a
string and saying
render("Hello world!")?

I've been trying to experiment with my own classes with this tactic, but
i'm new to ruby and can't get an example of the above working.
C40020a47c6b625af6422b5b1302abaf?d=identicon&s=25 Stefano Crocco (crocco)
on 2007-07-11 22:38
(Received via mailing list)
Alle mercoledì 11 luglio 2007, Max Williams ha scritto:
> I've been trying to experiment with my own classes with this tactic, but
> i'm new to ruby and can't get an example of the above working.

What is happening here is that you're calling the method render passing
hash as argument. In ruby, when you pass an hash as the last argument to
method, you may omit the usual braces, so the line you quoted is the
same as:

render( {:text => "Hello world!" } )

Usually, this is used to fake keyword arguments, which ruby doesn't
As an example, imagine you want to write a method which takes a string
does some of the following things:
* remove whitespace at the left, right or both
* makes the string downcase or upcase
* crypt it
You want the user to decide which of the previous transformation he
wants to
perform (of course, this is only an example; in reality, it might be
to create three separate methods). The method can be written this way:

def transform_string(orig, actions = nil ) #1
  default = { :remove_whitespace=>:both, :change_case=>nil, :crypt =>
nil} #2
  acts = actions || default
  temp = orig.dup #3

  if acts[:remove_whitespace] then #4
    case acts[:remove_whitespace]  #5
    when :left then temp.lstrip!   #6
    when :right then temp.rstrip!  #7
    when :left_right then temp.strip!  #8
    end  #9
  end   #10

  if acts[:change_case] == :downcase then temp.downcase!  #11
  elsif acts[:change_case] == :upcase then temp.upcase!   #12
  end                                                     #13

  temp = temp.crypt(acts[:crypt]) if acts[:crypt]         #14
  temp                                                    #15
end                                                       #16

In line 1, we define a method which takes a mandatory argument, the
modify, and an optional argument, a hash where the user will specify
actions he wants to perform.

In line 2, we create an hash with the default actions (the actions to
if the user didn't pass the optional argument). This hash contains three
entries, two of which are nil. The only non-nil one is
with content :both. Since actions whose value is nil won't be carried
this means that, if the user didn't specify an action, the method will
the whitespace both the left and the right of the string (the value
corresponding to :remove_whitespace in the hash is :both). In line 3, we
assign to the variable acts the hash containing the action specified by
user or, if this is nil (i.e, the user didn't specify any action), the
with the default actions.

In lines 4-10, depending on the content of the :remove_whitespace entry
acts, we remove the whitespace from the left, right, left and right of
string, or we leave it unchanged.

Likewise, in lines 11-13, if the action :change_case was specified, the
of the string is changed and, in line 14 we crypt the string if it was

In this example, the hash with the default actions wasn't used if the
specified the second parameter to the method. Often, you'll need to keep
default values for the keys the user doesn't specify. In this case, you
do the following:

def my_method( hash = {} )
  default_hash = { :opt_a => value_a, :opt_b => value_b }
  options = default_hash.merge(hash)

Here, the values to be used are obtained by merging the hash with the
options with the one passed as argument. This will overwrite the
elements in
default_hash which are also in hash, leaving the others unchanged.

I hope this helps

Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2007-07-11 22:40
(Received via mailing list)
On Jul 11, 2007, at 3:53 PM, Max Williams wrote:
> render("Hello world!")?
> I've been trying to experiment with my own classes with this
> tactic, but
> i'm new to ruby and can't get an example of the above working.

The trailing set of key => value pairs are turned into a hash passed
as the final argument to a method.  The fully punctuated version of
that is:

render({:text => "Hello world!"})

You'll often see methods defined as:

def my_method(arg1, arg2, options={})

when there is an optional set of options that can be passed in as a


Rob Biedenharn
73c04e9ef9ca435c5b19a2e765ae6d20?d=identicon&s=25 Max Williams (max-williams)
on 2007-07-12 01:03
That's an excellent and extremely illuminating explanation Stefano!
Thanks very much, you're a gent.

> I hope this helps
> Stefano
This topic is locked and can not be replied to.