既存クラスのメソッドに追加のオプションをつける方法
Rubyでselenium-webdriver
を使用してるときに
Selenium::WebDriver.for :phantomjs
driver.find_element(:id, "foo").clear
driver.find_element(:id, "foo").send_keys("bar")
のようにテキストボックスを埋める前にclear
で空にすることがよくあるために
send_keys(arg1, clear: true)
で事前に内容を消してから実行できるメソッドで置き換えをしようとしましたがうまくいきませんでした。
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
ですと、SystemStackError: stack level too deep
になってしまいました。
またメソッド名と同名のハッシュキーが使えなかったためclear_flag
にしています。
現状は別名のメソッドを使っています。既存クラスのメソッド置き換えは危険なのは理解してるのですが、個人的に使うものなので、長いメソッド名よりもキーワード引数で指定したく考えています。
class Selenium::WebDriver::Element
def send_keys_after_clear(*args)
clear
send_keys(args)
end
end
どのようにすればsend_keys(args, clear: true)
の形で上記の処理が実現できますか?
stack level too deep に関しての追記
問題が再現できなくなってしまっていたのですが、再現方法がわかりましたので追記しておきます。
send_keys
をオーバーライドしたメソッドを定義したファイルをselenium_webdriver_ext.rb
という名前で保存してpry
上で動かしていたのですが、他の部分を読み込み直すためにload 'selenium_webdriver_ext.rb'
を複数回読んでしまっていたためにオーバーライドしたメソッドを更にオーバーライドしようとし続けてエラーになっていたようです。
具体的を上げておきます。
[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