既存クラスのメソッドに追加のオプションをつける方法


Rubyで`selenium-webdriver`を使用してるときに

[code]

    Selenium::WebDriver.for :phantomjs
    driver.find_element(:id, "foo").clear
    driver.find_element(:id, "foo").send_keys("bar")
    
[/code]

のようにテキストボックスを埋める前に`clear`で空にすることがよくあるために  
`send_keys(arg1, clear: true)`で事前に内容を消してから実行できるメソッドで置き換えをしようとしましたがうまくいきませんでした。

[code]

    class Selenium::WebDriver::Element
      alias_method :send_keys_orig, :send_keys
      def send_keys(*args, clear_flag: false)
        clear if clear_flag
        send_keys_orig(*args)
      end
    end
    
[/code]

ですと、`SystemStackError: stack level too deep`になってしまいました。  
またメソッド名と同名のハッシュキーが使えなかったため`clear_flag`にしています。

現状は別名のメソッドを使っています。既存クラスのメソッド置き換えは危険なのは理解してるのですが、個人的に使うものなので、長いメソッド名よりもキーワード引数で指定したく考えています。

[code]

    class Selenium::WebDriver::Element
      def send_keys_after_clear(*args)
        clear
        send_keys(args)
      end
    end
    
[/code]

どのようにすれば`send_keys(args, clear: true)`の形で上記の処理が実現できますか？

### stack level too deep に関しての追記

問題が再現できなくなってしまっていたのですが、再現方法がわかりましたので追記しておきます。

`send_keys`をオーバーライドしたメソッドを定義したファイルを`selenium_webdriver_ext.rb`という名前で保存して`pry`上で動かしていたのですが、他の部分を読み込み直すために`load
'selenium_webdriver_ext.rb'`を複数回読んでしまっていたためにオーバーライドしたメソッドを更にオーバーライドしようとし続けてエラーになっていたようです。

具体的を上げておきます。

[code]

    [1] pry(main)> require 'selenium-webdriver'
    => true
    [2] pry(main)> driver = Selenium::WebDriver.for :firefox
    => #<Selenium::WebDriver::Driver:0x..f9315747cd0887642 browser=:firefox>
    [3] pry(main)> driver.navigate.to("http://google.co.jp")
    => ""
    [6] pry(main)> load 'selenium_webdriver_ext.rb'
    => true
    [7] pry(main)> driver.find_element(:id, "lst-ib").send_keys("foo")
    => ""
    [8] pry(main)> load 'selenium_webdriver_ext.rb'
    => true
    [9] pry(main)> driver.find_element(:id, "lst-ib").send_keys("foo")
    SystemStackError: stack level too deep
    
[/code]




同じ環境を作成してエラーを再現しようとしましたができませんでした。

こちらにコードを置いています。

<https://github.com/JunichiIto/sample-app-for-send_keys-alias/>

エイリアスメソッドはここで定義しています。

<https://github.com/JunichiIto/sample-app-for-send_keys-alias/blob/so-
sandbox/spec/support/selenium_support.rb>

`send_keys`メソッドを呼び出しているのはこちらです。

<https://github.com/JunichiIto/sample-app-for-send_keys-alias/blob/so-
sandbox/spec/features/users_spec.rb#L19>

RSpecでこのコードを実行すると、問題なくパスします。

![画像の説明をここに入力](https://i.stack.imgur.com/Ktb0s.png)

Rubyのバージョンは2.2.0、selenium-webdriverのバージョンは2.45.0.dev3です。  
（dev3を使っているのは[このエラー](https://stackoverflow.com/questions/28159499/seleniumwebdrivererrorjavascripterror-
arguments0-is-undefined)をなくすためです）

ご自身の環境に僕のコードをダウンロードしてみて問題が再現するか確認してみてください。




Ruby 2.0以上を使っているのであれば[Module#prepend](http://docs.ruby-
lang.org/ja/2.2.0/method/Module/i/prepend.html)を使うとalias method
chainのようなことをしなくても同じようなことが出来て便利です。

参考: [» Ruby2.0のModule#prependは如何にしてalias_method_chainを撲滅するのか！？ TECHSCORE
BLOG](http://www.techscore.com/blog/2013/01/22/ruby2-0%E3%81%AEmodule-
prepend%E3%81%AF%E5%A6%82%E4%BD%95%E3%81%AB%E3%81%97%E3%81%A6alias_method_chain%E3%82%92%E6%92%B2%E6%BB%85%E3%81%99%E3%82%8B%E3%81%AE%E3%81%8B%EF%BC%81%EF%BC%9F/)

[code]

    module SendKeysWithOption
      def send_keys(*args, clear: false)
        __send__(:clear) if clear
        super(*args)
      end
    end
    
    Selenium::WebDriver::Element.prepend(SendKeysWithOption)
    
[/code]

