今、リファクタリングRubyエディションを読んでいます。
テストコードが載っていないし、コードを補わないと動かなかったり、擬似コードで動かないコードが載っていたりして、ストレスマッハです。
6.17 動的メソッド定義(Dynamic Method Definition)のテストコードが書けたので、記事にします。
リファクタリング対象コードは、本では
def failure self.state = :failure end def error self.state = :error end def success self.state = :success end
となっていますが、stateはクラス変数で、アクセサを定義する必要があります。Ruby クラス変数のゲッタによると、クラス変数に対しては、attrなんとかでアクセサを定義することはできないそうなので、コードを書いて定義しました。リファクタリング対象コードは、次のようになります。
ファイル methodsample.rb
class MethodSample def state @@state end def state=(val) @@state = val end def failure self.state = :failure end def error self.state = :error end def success self.state = :success end end
これに対するテストコードは次のようになります。
ファイル test_methodsample.rb
require ‘test/unit’
require_relative ‘methodsample’
class TestMethodSample < Test::Unit::TestCase def setup @methodsample = MethodSample.new end def test_failure @methodsample.failure result = @methodsample.state expected_result = :failure assert_equal expected_result, result end def test_error @methodsample.error result = @methodsample.state expected_result = :error assert_equal expected_result, result end def test_success @methodsample.success result = @methodsample.state expected_result = :success assert_equal expected_result, result end end [/ruby] あと、この節のサンプル:def_eachを使って類似メソッドを定義するで、def_eachメソッドを定義するClassクラスは記述されているんですが、プロダクションコードでどう使うのか書かれていないので、補います。 ファイル methodsample.rb [ruby] require_relative 'class' class MethodSample def state @@state end def state=(val) @@state = val end def_each :failure, :error, :success do |method_name| self.state = method_name end end [/ruby] これは、Module#define_methodを抽象化する話を参考にさせていただきました。