QA@IT
«回答へ戻る

回答を投稿

はい。ご指摘の問題は既知のものではあったのですが、残念ながら実装の都合上どうしてもそうなってしまうので、つまりaction_argsの「仕様」です、というしかないところでした (gosub 言いわけ)。

が、よく考えてみたらRuby 2.0の素敵な新機能「キーワード引数」を使えばうまくいきそうな気がしたので、ちょっと実装してみました。 https://github.com/asakusarb/action_args/commit/04e6c8712a860c05052fd82eb4ea16ade2763293

もしよかったらこのGHの先っちょをbundleしてみて試してみていただけますか?


言いわけ: なぜメソッド仮引数にnil以外を設定しててもnilが渡されてしまうのか

そもそも今のRubyの仕様では、以下のように複数の省略可能なパラメーターが宣言されたメソッドに対して、arg1のデフォルト値を生かしながらarg2を渡すことができません。

def meth(arg1 = 1, arg2 = 2)
  ...
end

このメソッドをmeth(nil, 3)のように呼ぶとarg1: nil, arg2: 2になってしまうし、かと言ってmeth(3)ならarg1: 3, arg2: 2とみなされてしまいます。

action_argsでは、method宣言のparametersを見て、仮引数名をそのままキーにしてparamsから値を引っ張ってきてアクションメソッドの呼び出しに渡しているのですが、上記のケースを含む色んな形のメソッド定義に対応するために、ユーザーから値が渡されていようがいなかろうが、全ての省略可能パラメーターにnilを充填してやって呼び出しています。
たとえば、上記のアクションに対して飛んできたparamsが{arg2: 3}だった場合に、arg1: nilを補充して呼び出してやらないと、arg2のはずの値がarg1に渡されてしまう可能性があるからです。

この問題に完璧に対処するためには、メソッド呼び出しのパラメーターを定義された順序だけじゃなくて名前をキーにしたHashか何かで渡すことができれば良いんですけどね。あ、あれ?それってもしかして「キーワード引数」そのもの?
return。

はい。ご指摘の問題は既知のものではあったのですが、残念ながら実装の都合上どうしてもそうなってしまうので、つまりaction_argsの「仕様」です、というしかないところでした (gosub 言いわけ)。

が、よく考えてみたらRuby 2.0の素敵な新機能「キーワード引数」を使えばうまくいきそうな気がしたので、ちょっと実装してみました。 https://github.com/asakusarb/action_args/commit/04e6c8712a860c05052fd82eb4ea16ade2763293

もしよかったらこのGHの先っちょをbundleしてみて試してみていただけますか?

----

##### 言いわけ: なぜメソッド仮引数にnil以外を設定しててもnilが渡されてしまうのか

そもそも今のRubyの仕様では、以下のように複数の省略可能なパラメーターが宣言されたメソッドに対して、arg1のデフォルト値を生かしながらarg2を渡すことができません。
```ruby
def meth(arg1 = 1, arg2 = 2)
  ...
end
```

このメソッドを`meth(nil, 3)`のように呼ぶと`arg1: nil, arg2: 2`になってしまうし、かと言って`meth(3)`なら`arg1: 3, arg2: 2`とみなされてしまいます。

action_argsでは、method宣言の`parameters`を見て、仮引数名をそのままキーにして`params`から値を引っ張ってきてアクションメソッドの呼び出しに渡しているのですが、上記のケースを含む色んな形のメソッド定義に対応するために、ユーザーから値が渡されていようがいなかろうが、全ての省略可能パラメーターにnilを充填してやって呼び出しています。
たとえば、上記のアクションに対して飛んできたparamsが`{arg2: 3}`だった場合に、arg1: nilを補充して呼び出してやらないと、arg2のはずの値がarg1に渡されてしまう可能性があるからです。

この問題に完璧に対処するためには、メソッド呼び出しのパラメーターを定義された順序だけじゃなくて名前をキーにしたHashか何かで渡すことができれば良いんですけどね。あ、あれ?それってもしかして「キーワード引数」そのもの?
return。