Passing Hashes Instead of Method Parameters

Passing hashes instead of method parameters

Both approaches have their own advantages and disadvantages, when you use an options hash replacing standard arguments you lose clarity in the code defining the method but gain clarity whenever you use the method because of the pseudo-named paramaters created by using an options hash.

My general rule is if you either have a lot of arguments for a method (more than 3 or 4) or lots of optional arguments then use an options hash otherwise use standard arguments. However when using an options hash it is important to always include a comment with the method definition describing the possible arguments.

Accepting either a hash or an array of hashes as arguments to a Ruby method

For me, the best solution is to change the method to:

def self.store(*hashes)
params = hashes.flatten
puts params.inspect
end
  • If you pass a single hash, it will be an array
  • If you pass an array of hashes, it remains the same
  • If you pases N hashes, it compacts all parameters into a one dimensional array.

You can pass whatever you want.

self.store({:key => 'value'}) # => [{:key => 'value'}]
self.store({:key => 'value'}, {:foo => 'bar'}) # => [{:key => 'value'}, {:foo => 'bar'}]
self.store([{:key => 'value'}, {:foo => 'bar'}]) # => [{:key => 'value'}, {:foo => 'bar'}]

How do methods use hash arguments in Ruby?

Example:

def foo(regular, hash={})
puts "regular: #{regular}"
puts "hash: #{hash}"
puts "a: #{hash[:a]}"
puts "b: #{hash[:b]}"
end

foo("regular argument", a: 12, :b => 13)

I use hash={} to specify that the last argument is a hash, with default value of empty hash. Now, when I write:

foo("regular argument", a: 12, :b => 13)

It's actually a syntactic sugar for:

foo("regular argument", {a: 12, :b => 13})

Also, {a: 12} is syntactic sugar for {:a => 12}.

When all of this is combined together, you get a syntax that looks similar to named arguments in other languages.

Passing Hash values as parameters to methods in Ruby

Thats easy

met1("abc" => "xyz")

def met1(options)
puts options
# with key
puts options["abc"]
end

I assume you know what the options might contain in terms of keys right? if not,

def met1(options)
puts options.keys # options is the hash you passed it, use it like one
end

In Ruby, how can you pass more than one hash to a method, without parentheses?

Mu points out that you can pass multiple hashes without parentheses, if you pass them in as non-literals i.e. as variables.

But other than that, so, for literal hashes,

You do(need parentheses to pass multiple literal hashes), unless you are passing keyword arguments.. You can pass multiple keyword arguments without parentheses.

a keyword argument would be when the parameters of the method include a colon like e.g. def blah x:, y: then you can call with blah y:2,x:3 . Sometimes you have to look at the parameter(s) to see if an argument is a keyword argument, e.g. if you have a method called with abc x:3
then that might be def abc x: in which case you called it with a keyword argument. Or it might be def abc x in which case you called it with a hash, omitting the {}.

When I say keyword argument, I don't mean a hash.. and vice versa, when I say hash I mean not a keyword argument.

When a call is without parentheses, you can only pass one hash and that hash has to be the last argument. And you can skip the {} around it.

note- I'm no expert, but as to a related question of whether a keyword argument is a type of hash, from what I understand, as of writing, pre ruby 3, they are, but there is a proposal for ruby 3 to have 'real' keyword arguments that are distinct from hashes https://bugs.ruby-lang.org/issues/14183

a keyword argument can't be multi-valued.

also, a hash can be automatically converted to a keyword argument. (e.g. if a method is defined with a parameter that is a keyword argument, you can pass a hash in e.g. {x:"a"} , that x being a symbol, and that hash will be converted to a keyword argument x:"a" (that x being a parameter name).

I'll add a point regarding blocks and parentheses, because a block done with {} does look a little bit like a hash though is not a hash. And a block can have some influence on whether parentheses are needed.

If you see abc {}, that {} is a block not a hash, and blocks don't count as an argument. Hence that call works for def abc but not for def abc x where one would get an error related to number of arguments passed.

even when passing a block after some other arguments, there should be no comma before the block, and if a block done with {} follows some arguments, you need parentheses, but if a block done with do .. end follows some arguments, you don't need parentheses

it is suggested that one use parentheses when one has multiple arguments, unless it's a DSL(domain specific language). Do you leave parentheses in or out in Ruby?

Create a ruby method that accepts a hash of parameters

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

Passing a hash as arguments in Ruby

Use the double splat operator (**) to convert the hash into keyword arguments.

user = User.from_google(**from_google_params)

The separation of keywords and positional arguments was a big change in Ruby 3. Previous versions of Ruby would coerce the last positional argument into keywords if its a hash - this behavior was depreciated in Ruby 2.7 and removed completely in 3.0.



Related Topics



Leave a reply



Submit