2017-01-25 22 views
1

メソッドにデフォルト引数のみがある間に、動的引数(* args、** kwrags)を使用してメソッドを呼び出すためにsendを使用する方法があるかどうかを調べようとしています。私はいくつかの条件をチェックする必要があるモジュールを持っているデフォルト引数を持つメソッドに動的引数を送信する方法

class Worker 
    def perform(foo='something') 
    # do something 
    end 
end 

は、以下のクラスを考えます。 条件が満たされていない場合、#performメソッドを実行する必要があります一度ワーカークラスのモジュールを含む

module SkippableWorker 
    def self.included(base) 
    base.class_eval do 
     alias_method :skippable_perform, :perform 
     define_method :perform do |*args, **keyword_args| 
     return if skip? 
     self.send(:skippable_perform, *args, **keyword_args) 
     end 

     define_method :skip? do 
     # checks whether to skip or not 
     end 
    end 
    end 
end 

を、私は モジュールのsendコマンドで問題が発生します。

self.send(:skippable_perform, *args, **keyword_args) 

の場合#performを呼び出してデフォルトの引数を使用したい場合、呼び出しは引数なしで行われます。

Worker.new.perform() 

しかし、sendコマンドiモジュールは* argsと** kwargsを[]と{}に変換します。したがって、#performの呼び出しは、argsの量が不一致のArgumentErrorを引き起こすsend(:perform、[]、{})に終わり、少なくとも送信することを意味するものではない値を送信しますデフォルトの「何か」)。

これを解決する方法はありますか?

+2

kwargsを方程式から削除すると、すべてが[作業を開始]します(http://pastebin.com/qt84MvnR)。 –

+0

ありがとう@SergioTulentsev、これは実際に動作し、私は詳細な答えを感謝します。 誰かがkwargsのアイデアを思い付くならば、試してみてください。 –

答えて

2

問題

私が見つけた最高の説明はhereました。

**{}は、kwargsが空のハッシュであっても、**kwargsと同じ方法で解析されません。

keyword_args.empty?

skippable_performを呼び出す前に、kwargsが空であるかどうかを確認するのが簡単な解決策です。

完全なコードは次のようになります。

module SkippableWorker 
    def self.included(base) 
    base.class_eval do 
     alias_method :skippable_perform, :perform 
     define_method :perform do |*args, **keyword_args| 
     return if skip? 
     if keyword_args.empty? 
      self.send(:skippable_perform, *args) 
     else 
      self.send(:skippable_perform, *args, **keyword_args) 
     end 
     end 

     define_method :skip? do 
     puts self.class 
     if rand > 0.5 
      puts " Skipping" 
      true 
     end 
     end 
    end 
    end 
end 

class Worker 
    def perform(foo='standard arg') 
    puts " #{foo}" 
    end 
    include SkippableWorker 
end 

class AnotherWorker 
    def perform(bar:'standard kwarg') 
    puts " #{bar}" 
    end 
    include SkippableWorker 
end 

Worker.new.perform 
Worker.new.perform 
Worker.new.perform('another arg') 
Worker.new.perform('another arg') 
AnotherWorker.new.perform 
AnotherWorker.new.perform 
AnotherWorker.new.perform(bar: 'another kwarg') 
AnotherWorker.new.perform(bar: 'another kwarg') 

randによっては、それができた出力:

Worker 
    standard arg 
Worker 
    Skipping 
Worker 
    Skipping 
Worker 
    another arg 
AnotherWorker 
    standard kwarg 
AnotherWorker 
    standard kwarg 
AnotherWorker 
    Skipping 
AnotherWorker 
    another kwarg 

方法#パラメータ

もう一つの方法は、skippable_performが期待されているパラメータをチェックすることです:

method(:skippable_perform).parameters.any?{|type,name| type == :key} 

となり、結果によってはdefine_methodとなります。

+0

ありがとう、良いアイデア! –

関連する問題