MOE3: Unit#to_s メソッド

Unit の文字列化

Unit#to_s への要求仕様は至極単純。

仕様 1

例えば「Lon にいる海軍」の #to_s を呼んだら "F Lon" を返す。

陸軍なら "A Lon" を返す。

最初の文字が "A""F" かの違いだけなので、メソッド本体は Unit#to_s として実装してしまい、差分を ArmyFleet で吸収する形が自然な発想だろう。

それからもう一点、この先 Order#to_s に関係してくるはずの仕様として、引数に Power を一つ渡せるようにする。

仕様 2

引数として Power が渡された場合、その軍の所属国、すなわち Unit#power と引数の Power が一致しなければ、Unit#to_s は戻り値に所属国の genitive を付与する。

前述の「Lon にいる海軍」の所属国が英で、Fleet#to_s に渡された Power が仏であれば、Fleet#to_s"English F Lon" を返すのが正しい。

実装

実際に呼ばれるのは Army#to_s または Fleet#to_s であって、Unit#to_s が直接呼ばれることはない。しかし派生クラスにしか存在しない symbol メソッドを Unit#to_s から呼び出すのが気持ち悪かったのでこうなった。

class Unit < ActiveRecord::Base
  belongs_to :phase
  belongs_to :power
  belongs_to :province

  def symbol
    # 派生クラスでオーバーライド
  end

  def to_s(owner = power)
    result = "%s %s"%[symbol, province.shortname]
    result = "%s %s"%[power.genitive, result] if owner != power
    result
  end
end

徹底するなら Unit#symbol では例外投げるべきだろうけど、単なる気休めなのでそこまでは必要なかろう。

class Army < Unit
  def symbol
    "A"
  end
end
class Fleet < Unit
  def symbol
    "F"
  end
end

ちなみに Province#shortname はメソッド、Province#codePower#genitive は属性である。

class Province < ActiveRecord::Base
  belongs_to :homepower, class_name:"Power"

  def shortname
    code.capitalize
  end
end
class Power < ActiveRecord::Base
end