63

I don't know how to create a ruby method that accepts a hash of parameters. I mean, in Rails I'd like to use a method like this:

login_success :msg => "Success!", :gotourl => user_url

What is the prototype of a method that accepts this kind of parameters? How do I read them?

vvvvv
  • 25,404
  • 19
  • 49
  • 81
collimarco
  • 34,231
  • 36
  • 108
  • 142

4 Answers4

67

If you pass paramaters to a Ruby function in hash syntax, Ruby will assume that is your goal. Thus:

def login_success(hsh = {})
  puts hsh[:msg]
end
Allyn
  • 20,271
  • 16
  • 57
  • 68
  • Can't I use something like login_success(*params)? – collimarco Feb 24 '09 at 20:27
  • 5
    a * (aka splat operator) means that method accepts any number of args and will put them in an array called params. Deciding on whether to use it or not depends on what you're after. In the example you provided, a hash makes sense. – Allyn Feb 24 '09 at 20:42
  • 6
    That says you are expecting any number of arguments. Like `foo(1, :b, '3')`. Also, you don't need the "={}" part of that. this will work fine: def login_success(hash). The above code just sets the default as an empty hash. – Alex Wayne Feb 24 '09 at 20:43
33

A key thing to remember is that you can only do the syntax where you leave out the hash characters {}, if the hash parameter is the last parameter of a function. So you can do what Allyn did, and that will work. Also

def login_success(name, hsh)
  puts "User #{name} logged in with #{hsh[:some_hash_key]}"
end

And you can call it with

login_success "username", :time => Time.now, :some_hash_key => "some text"

But if the hash is not the last parameter you have to surround the hash elements with {}.

scottd
  • 7,364
  • 1
  • 24
  • 27
14

With the advent of Keyword Arguments in Ruby 2.0 you can now do

def login_success(msg:"Default", gotourl:"http://example.com")
  puts msg
  redirect_to gotourl
end

In Ruby 2.1 you can leave out the default values,

def login_success(msg:, gotourl:)
  puts msg
  redirect_to gotourl
end

When called, leaving out a parameter that has no default value will raise an ArgumentError

user160917
  • 9,211
  • 4
  • 53
  • 63
  • 3
    You might also want to mention that you can leave out the default values in Ruby 2.1 to make the parameters required, e.g. `def login_success(msg:, gotourl:)` will result in an error being raised if you try to call `login_success` without both the `msg` and `gotourl` parameters being specified. – Ajedi32 Apr 30 '15 at 13:41
5

Use one single argument. Ruby will transform the named values into a hash:

def login_success arg
 # Your code here
end

login_success :msg => 'Success!', :gotourl => user_url
# => login_success({:msg => 'Success!', :gotourl => user_url})

If you really want to make sure you get a hash, instead of the default ruby duck typing, then you would need to control for it. Something like, for example:

def login_success arg
  raise Exception.new('Argument not a Hash...') unless arg.is_a? Hash
  # Your code here
end
CCD
  • 336
  • 3
  • 3