nilガード
def nil_guard( val=nil )
val ||= "default"
end
p nil_guard()
# "default"
p nil_guard( "test" )
# "test"
本来nilガードはその変数が未定義でもその場で定義もできちゃうところが強力ですが、引数処理にも使えます.
引数デフォルトにval="default"
としてもいいですが、nilが格納された変数が明示的に渡される場面も多いのでnilを防ぎたい局面では有効です.
p nil_guard( false )
# "default"
falseを明示的に引数に渡したいときは注意です.
キーワード引数で必須項目
ruby2.1以降ではキーワード引数の特定の属性を必須化できます.
ラベルの後にデフォルト値を書かなければ必須項目となります.
def required_keyword_args(first_name:, last_name:, age: nil)
"#{first_name}, #{last_name} (#{age.to_s})"
end
p required_keyword_args()
# ArgumentError
p required_keyword_args(first_name: "Isaac")
# ArgumentError
p required_keyword_args(first_name: "Isaac", last_name: "Newton")
# "Isaac, Newton ()"
p required_keyword_args(first_name: "Isaac", last_name: "Newton", age: 30)
# "Isaac, Newton (30)"
可変長引数(アスタリスク)
引数に*
をつけると可変長になります.
以下例のように前方から必須化することもできます.
def variadic(arg1, arg2, *others)
p arg1
p arg2
p others
end
variadic(1,2,3,4,5)
# 1
# 2
# [3, 4, 5]
variadic(1,2)
# 1
# 2
# []
引数に**
をつけるとキーワード引数をハッシュで受け取ることができます.
def variadic_keyword(arg, *array_args, **hash_args)
p arg
p array_args
p hash_args
end
variadic_keyword(1,2,3,4,5)
# 1
# [2, 3, 4, 5]
# {}
variadic_keyword(1,2,3, april:"spring", july:"summer")
# 1
# [2, 3]
# {:april=>"spring", :july=>"summer"}
variadic_keyword(1,april:"spring", july:"summer")
# 1
# []
# {:april=>"spring", :july=>"summer"}
ちなみに変数定義時ではなく、変数呼び出し時に引数に*
をつけると配列を引数として渡すことができます.
**
をつければハッシュをキーワード引数として展開できます.
primes = [2,3,5,7,11,13]
variadic(*primes)
# 2
# 3
# [5, 7, 11, 13]
monthes = {april:"spring",may:"spring"}
variadic_keyword(1,2,3,**monthes)
# 1
# [2, 3]
# {:april=>"spring", :may=>"spring"}
stringify_keys
rubyではhashのキーがstringかsymbolかを間違えてはまることがよくあります.
active supportのstringify_keys
を使うとハッシュのキーをstringに変換できます.
どちらの形式でもうまく動くようにメソッドが設計されていると親切だと思います.
require "active_support"
require "active_support/core_ext"
def stringify( hash )
hash = hash.stringify_keys
end
p stringify( january:"winter", february:"winter" )
# {"january"=>"winter", "february"=>"winter"}
ネストされたハッシュのキーをstringifyするにはdeep_stringify_keys
を使います.
symbolize_keys
stringify_keys
の逆をやりたいときはsymbolize_keys
です.
require "active_support"
require "active_support/core_ext"
def symbolize( hash )
hash = hash.symbolize_keys
end
p symbolize( "january"=>"winter", "february"=>"winter" )
# {:january=>"winter", :february=>"winter"}
ネストされたハッシュのキーをsymbolizeするにはdeep_symbolize_keys
を使います.
with_indifferent_access
active supportのwith_indifferent_access
メソッドを使うと、stringでもsymbolでもアクセスできるハッシュを作成できます.
ハッシュが拡張されたActiveSupport::HashWithIndifferentAccess
オブジェクトが返されます.
require "active_support"
require "active_support/core_ext"
def indifferent_access( hash )
hash = hash.with_indifferent_access
p hash[:january]
p hash["january"]
p hash[:february]
p hash["february"]
p hash[:march]
p hash["march"]
end
indifferent_access( "january"=>"1月", "february"=>"2月", march: "3月" )
# "1月"
# "1月"
# "2月"
# "2月"
# "3月"
# "3月"
hash delete
Hash#delete
メソッドは、レシーバのハッシュからデータ削除し、削除されたvalueを返します. この特徴を使って、たとえば1つのキーワード引数集合の中から性質の異なる属性を抜き出すことができます.
def hash_delete( hash )
text_color = hash.delete(:text_color)
p text_color
p hash
end
hash_delete(first_name:"Issaac", last_name:"Newton", text_color:"red")
# "red"
# {:first_name=>"Issaac", :last_name=>"Newton"}
railsのform helperをラップしたメソッドを作って独自オプションを追加したいときなどに便利です.
def custom_text_field( name, value, options={} )
error_message = options.delete :error_message
tag_html = text_field_tag( name, value, options )
wrap_with_validation_error( tag_html, error_message: error_message )
end
assert_valid_keys
active supportのassert_valid_keys
は許可するハッシュキーだけを通して、それ以外のものが含まれたら例外を投げます.
require "active_support"
require "active_support/core_ext"
def assert_args( **args )
args.assert_valid_keys(:first_name, :last_name)
end
assert_args( first_name: "Issaac" )
# last_nameが足りないが例外にはならない
assert_args( first_name: "Issaac", last_name: "Newton" )
# 許可リストのキーしか含まないため問題なし
assert_args( first_name: "Issaac", last_name: "Newton", age: 30 )
# 許可リスト以外のキー(age)が含まれるため例外
# Unknown key: :age. Valid keys are: :first_name, :last_name (ArgumentError)
Environment
% ruby -v
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
他にも引数処理に使える便利な方法があれば教えてください.