2016-07-27 12 views
1
  1. ちょっとそこRubyのオプションのオプションを持つ方法と&ブロックパラメータ

    それはメソッド呼び出しのパラメータ として任意の属性やブロックを持つことは可能ですか?

    例:私は

    method(foo, foo: bar, -> { do_something } 
    

    を呼び出す必要があり、ブロックは常に最後の位置になければならない私の理解については

    def method(foo, *bar, &block) 
    end 
    

    でそれを試してみましたか?

    少しの研究の後、私は単項(?)を見つけた*は 配列のようです。私はHashに合格しようとしているので、私は

    def method(foo, bar={}, &block) 
    end 
    

    にコードを変更しかし、これはどちらかのトリックを行いません。私は彼が傾けることができないと思う。 バーがどこで終わり、ブロックが始まるのか把握する。

    アイデアや提案はありますか?事前にありがとう

    追加:私はこれがなぜ必要なのか不思議です。私たちは大きなjson スキーマを実行しており、 モデル定義からjsonを構築する小さなDSLを持っています。詳しく説明することなく、 にexportable_scopesを実装したかったのです。いくつかの初期化子で

    class FooBar 
        exportable_scope :some_scope, title: 'Some Scope', -> { rewhere archived: true } 
    end 
    

    これが起こることになっている:

    def exportable_scope scope, attributes, &block 
        scope scope block 
        if attributes.any? 
        attributes.each do |attribute| 
         exportable_schema.scopes[scope] = attribute 
        end 
        else 
        exportable_schema.scopes[scope] = {title: scope} 
        end 
    end 
    

    だから、これが正常に動作している、私はちょうど方法 パラメータのためのヒントを必要としています。

+0

私は、 'exportable_scope(:some_scope、title: 'Some Scope'){rewhere archived:true}'を使うことができます。 parametterのようなブロックを送る必要はありません。 –

+1

私は、ActiveRecordの '.scope'が受け取ると思われる引数として呼び出し可能なオブジェクト(lambda)を渡してブロックを渡すのを混乱させると思います。スコープの本体が必要なので、メソッドのシグネチャを 'exportable_scope(name、body、attributes = {})'に変更し、 'scope name、body'を呼び出すことができます。ここで '.scope'の定義を見てください:https://github.com/rails/rails/blob/dc925119a3912ecfe0df400007163f33b99d6385/activerecord/lib/active_record/scoping/named.rb#L143。 'exportable_scope:some_scope、 - > {rewhere archived:true}、タイトル: 'Some Scope''。 –

答えて

1

はい、可能です。

パラメータの種類を混合する場合、それらは特定の順序で方法の定義に含まれなければならない。

  1. 位置パラメータ(必須およびオプション)と単一スプラットパラメータ、任意の順序で。
  2. 任意の順序でキーワードパラメータ(必須およびオプション)。
  3. ダブルスプラットパラメータ。
  4. ブロックパラメータ(接頭辞は&)。

上記の注文は多少柔軟です。メソッドを定義して、単一のスプラット引数、次に2つのオプションの位置引数などを使用してパラメータリストを開始できます。 Rubyはそれを許していますが、コードは読みにくく、デバッグするのが難しいため、通常は非常に悪い習慣です。通常、次の順序を使用するのが最善です。

  1. 必要な位置パラメータ。
  2. オプションの位置パラメータ(デフォルト値)。
  3. シングルスプラットパラメータ。
  4. キーワードパラメータ(必須およびオプション、その順序は関係ありません)。
  5. ダブルスプラットパラメータ。
  6. 明示的ブロックパラメータ(接頭辞&)。

例:

def meditate cushion, meditation="kinhin", *room_items, time: , posture: "kekkafuza", **periods, &b 
    puts "We are practicing #{meditation}, for #{time} minutes, in the #{posture} posture (ouch, my knees!)." 
    puts "Room items: #{room_items}" 
    puts "Periods: #{periods}" 
    b.call # Run the proc received through the &b parameter 
end 

meditate("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon") { puts "Hello from inside the block" } 

# Output: 
We are practicing zazen, for 40 minutes, in the kekkafuza posture (ouch, my knees!). 
Room items: ["zabuton", "incense"] 
Periods: {:period1=>"morning", :period2=>"afternoon"} 
Hello from inside the block 

お知らせメソッドを呼び出すときに、我々が持っている:クッション必須位置引数を提供

  • 瞑想オプションの位置引数のデフォルト値を上書きします。
  • * room_itemsパラメータでいくつかの余分な位置引数(zabutonとincense)を渡しました。
  • 時間必須のキーワード引数を指定しました。
  • postureオプションのキーワード引数を省略しました。
  • ** periodsパラメータを使用して、いくつかの余分なキーワード引数(period1: "morning"、period2: "afternoon")を渡しました。
  • ブロック{Hello from block from}を& bパラメータに渡しました。

上記の例は、さまざまな種類のパラメータを混在させる可能性を説明するためのものです。このようなメソッドを実際のコードに組み込むのは悪い習慣です。メソッドに多くの引数が必要な場合は、おそらくそれをより小さなメソッドに分割することが最善です。その多くのデータを単一のメソッドに渡すことが絶対必要な場合は、データをより組織的に格納するクラスを作成し、そのクラスのインスタンスを単一の引数としてメソッドに渡す必要があります。

関連する問題