I have a hash like this hash = {"band" => "for King & Country", "song_name" => "Matter"}
and a class:
class Song
def initialize(*args, **kwargs)
#accept either just args or just kwargs
#initialize @band, @song_name
end
end
I would want to pass the hash
as keyword arguments like Song.new band: "for King & Country", song_name: "Matter"
Is it possible?
Kwargs allow you to pass keyword arguments to a function. They are used when you are not sure of the number of keyword arguments that will be passed in the function. Kwargs can be used for unpacking dictionary key, value pairs. This is done using the double asterisk notation ( ** ).
So when you want to pass keyword arguments, you should always use foo(k: expr) or foo(**expr) . If you want to accept keyword arguments, in principle you should always use def foo(k: default) or def foo(k:) or def foo(**kwargs) .
A keyword argument is a name-value pair that is passed to the function. Here are some of the advantages: If the values passed with positional arguments are wrong, you will get an error or unexpected behavior. Keyword arguments can be passed in any order.
In the code you posted, *args simply indicates that the method accepts a variable number of arguments in an array called args . It could have been called anything you want (following the Ruby naming rules, of course).
You have to convert the keys in your hash to symbols:
class Song
def initialize(*args, **kwargs)
puts "args = #{args.inspect}"
puts "kwargs = #{kwargs.inspect}"
end
end
hash = {"band" => "for King & Country", "song_name" => "Matter"}
Song.new(hash)
# Output:
# args = [{"band"=>"for King & Country", "song_name"=>"Matter"}]
# kwargs = {}
symbolic_hash = hash.map { |k, v| [k.to_sym, v] }.to_h
#=> {:band=>"for King & Country", :song_name=>"Matter"}
Song.new(symbolic_hash)
# Output:
# args = []
# kwargs = {:band=>"for King & Country", :song_name=>"Matter"}
In Rails / Active Support there is Hash#symbolize_keys
As Stefan mentions, in Rails we have access to symbolize_keys
that works like this:
{"band" => "for King & Country", "song_name" => "Matter"}.symbolize_keys
#=> {:band=>"for King & Country", :song_name=>"Matter"}
It's also aliased as: to_options
, hence:
{"band" => "for King & Country", "song_name" => "Matter"}.to_options
#=> {:band=>"for King & Country", :song_name=>"Matter"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With