web-dev-qa-db-ja.com

Ruby 2.xで必須の名前付きパラメーターを使用できますか?

Ruby 2.0は、次のような名前付きパラメーターを追加しています。

def say(greeting: 'hi')
  puts greeting
end

say                     # => puts 'hi'
say(greeting: 'howdy')  # => puts 'howdy'

デフォルト値を指定せずに名前付きパラメーターを使用するにはどうすればよいですか?

47
Nathan Long

Ruby 2.0.0には特定の方法はありませんが、 できますRuby 2.1.def foo(a:, b:) ...

Ruby 2.0.xでは、例外を発生させる任意の式を配置することでそれを強制できます。例:

def say(greeting: raise "greeting is required")
  # ...
end

これを頻繁に行う予定がある場合(およびRuby 2.1+)を使用できない場合)、次のようなヘルパーメソッドを使用できます。

def required
  method = caller_locations(1,1)[0].label
  raise ArgumentError,
    "A required keyword argument was not specified when calling '#{method}'"
end

def say(greeting: required)
  # ...
end

say # => A required keyword argument was not specified when calling 'say'
90

現時点(Ruby 2.0.0-preview1)では、次のメソッドシグネチャを使用できます。

_def say(greeting: greeting_to_say)
  puts greeting
end
_

_greeting_to_say_は単なるプレースホルダーであり、名前付きパラメーターに引数を指定した場合は評価されません。それを渡さない場合(say()だけを呼び出す)、Rubyはエラーを発生させます:

_NameError: undefined local variable or method `greeting_to_say' for (your scope)
_

ただし、その変数は何にもバインドされておらず、私が知る限り、メソッド内から参照することはできません。名前付きパラメーターに渡されたものを参照するローカル変数として、引き続きgreetingを使用します。

実際にこれを行う場合def say(greeting: greeting)を使用して、エラーメッセージがパラメータに付けた名前を参照するようにすることをお勧めします。上記の例では、必要な名前付きパラメーターに引数を指定しない場合に表示されるエラーメッセージでRubyが使用するものを説明するために、異なるもののみを選択しました。

正直なところ、say('hi') Rubyを呼び出すと、ArgumentError: wrong number of arguments (1 for 0)が発生します。これは少し混乱すると思いますが、プレビュー1のみです。

19
Adam

@awendtと@Adamのソリューションを組み合わせると、

def say(greeting: ->{ raise ArgumentError.new("greeting is required") }.call)
  puts greeting
end

DRYこれは次のようになります:

def required(arg)
  raise ArgumentError.new("required #{arg}")
end

def say(greeting: required('greeting'))
  puts greeting
end

そしてそれを@ Marc-Andreのソリューションと組み合わせる: https://Gist.github.com/rdp/5390849

11
Ben Taitelbaum

Ruby 2.3では、私はできる

def say(greeting:)
  puts greeting
end

次に、それを使用して...

say(greeting: "hello there")
3
thedanotto

どうですか:

def say(greeting: nil)
  greeting or raise ArgumentError
  puts greeting
end

say                     # => raises ArgumentError
say(greeting: 'howdy')  # => puts 'howdy'

それ以外は難しいでしょう。 このサイト によると、キーワード引数は「デフォルト値を持つ名前付きパラメータです。」

3
awendt