Personal tools
You are here: Home 清水川記 BattleLine RoR (2)
Document Actions

BattleLine RoR (2)

バトルライン(1/19時点)

1/19日時点でカードに色を付けて手札をソートするようにしたら、格段に見やすくなってゲームに集中できるようになった。やっぱり見た目のわかりやすさは重要。あと人間がものを判別するときってかなり色に頼ってるんだなぁと思った。識別のための配色は重要。

スナップショットでは左の手札のところがラジオボタンとカードの位置がずれていて縦に伸びてしまっている。カードに画像を使えば簡単に直せそうなんだけど、とりあえずは画像は無しで。

次の目標は、実際のカードを使ったプレート同じように、場のカードの並べ方を右に90度回転させて、自分の置いたカードが手前側に表示されるようにして、より分かりやすくすることかな!

勉強したこと

RoR: 命名規約に沿っていないクラスをserializeすると復元出来ない

System Message: WARNING/2 (<string>, line 12)

Title underline too short.

RoR: 命名規約に沿っていないクラスをserializeすると復元出来ない
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BattleLine RoR (1) では部隊カードの山札を格納する変数 troops や戦術カード山札の tactics を以下のように実装していた。

app/models/round.rb
class Round < ActiveRecord::Base
  
serialize :troops, Array
  
...

  
def setup
    
self.troops = ['A1','A2','A3',...,'B1','B2',...].sort_by{rand}
    
self.tactics = ['ALEXANDER','DARIUS',...,'REDEPLOY',...].sort_by{rand}
    
...
  
end
end

このままだと色づけのためのスタイルシートclassの設定とか諸々がif文の嵐になってしまうので、Cardクラスを作ってゲームに使用するカードは全てCardクラスの派生クラスとして再実装した。

lib/card.rb
class Card
  
...
  
def self.new_troops
    
TROOP_NAMES.collect{|name| TroopCard.new name}
  
end
  
def self.new_tactics
    
TACTICS_NAMES.collect{|name| TacticsCard.new name}
  
end
end

class TroopCard < Card
  
...
end

class TacticsCard < Card
  
...
end

で、改めてround.rbの実装を以下のように書き直した。

app/models/round.rb
class Round < ActiveRecord::Base
  
serialize :troops, Array
  
...

  
def setup
    
self.troops = Card.new_troops.sort_by{rand}
    
self.tactics = ...
    
...
  
end
end

そうしたところ、画面表示にエラーが出るようになってしまったので、script/console で原因を確認したところ、保存してあったRoundレコードを読み込んだときにtroopsが正しくロードされなくなってしまっていた!

ruby script/console
>> round = Round.last
>> round.troops[0]
=> #<YAML::Object:0x5832ad4 @ivars={"name"=>"A1"}, @class="Card">

なんじゃこりゃ。#<YAML::Object .. ってYAMLのクラス?なんでTroopCardじゃないんだろう?

(...試行錯誤1時間くらい...)

round.rb で require 'card' してあげたらちゃんとロード出来るようになった。

ruby script/console
>> round = Round.last
>> round.troops[0]
=> #<TroopCard:0x4f12a1c @name="A1">

Rails の仕組みで、正しい名前のクラスなんかは自動的にファイルから読み込んでロードしてくれるようになっているけど、lib/card.rb ファイルに実装したTroopCardクラスはシリアライズした文字列からオブジェクトに戻す時に不明なクラス扱いされてしまっていたらしい。とりあえずrequire 'card'ってしておいたら、ちゃんと TroopCardクラスのインスタンスに戻してくれるようになった。

でも、そんな細かいクラス一つ一つのために命名規約に沿ってファイルを分けるの面倒くさいよ?

RoR: lib以下のファイルは自動再読み込みしてくれない

lib以下のファイル、というよりは特定のクラスの派生クラスしか自動再読込してくれないっぽい。コントローラやモデルなんかは自動再読込してくれるけど、独自に作ったクラスはだめだった。試しにlib以下じゃなくてmodels以下に置いてみたけどやっぱり駄目だった。

で、色々調べていったところ、Railsで行われている自動リロードは以下のような手順で実現しているっぽい。

  1. active_support/dependencies.rbでModelとClassに const_missing メソッドが定義されていて、定数(クラスとか)が無い場合に自動ロードする仕組みになっている
  2. Rails(というか今回調べたのはMongrel)はRequest処理が終わる毎にリロード可能なクラスとかを無効化(unload)している
  3. 無効化のためにactive_support/dependencies.rbの Dependencies.clear が呼び出されている
  4. 次のRequest時にはunloadされた定数が見つからないので const_missing でリロードされる

このとき無効化されるクラスはActiveRecord::Baseの継承クラスとか特定のクラスに限られるっぽい。

じゃあ、無効化される対象クラスにするにはどうすれば良いのか...と思ってさらに active_support/dependencies.rb を読んだところ、 Model, Class, Object に unloadable というメソッドが追加されていて、これ呼び出すと Dependencies.clear でunloadされるようになるらしい。

実際ちゃんと動くかどうか以下のようにして試してみた。

lib/foo.rb
class Foo
  
puts 'class Foo loaded!'
end
Foo.unloadable
ruby script\console
Loading development environment (Rails 2.1.0)
>> Foo
class Foo loaded!
=> Foo
>> Foo
=> Foo
>> Dependencies.clear
=> ["Foo"]
>> Foo
class Foo loaded!
=> Foo

/* modify puts line in foo.rb */

>> Dependencies.clear
=> ["Foo"]
>> Foo
class Foo loaded! loaded! yahoo!!
=> Foo

うまくいったっぽい!

しかし、Railsで使う用の独自クラス(Card)に上記を適用してみたところ、serializeで独自クラスを含むArray, Hashの復元がうまくいかなくなってしまった‥‥。あちらを立てればこちらが立たず。あと一歩というところなんだけどなぁ。

The URL to Trackback this entry is:
http://www.freia.jp/taka/blog/620/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)

« July 2010 »
Mo Tu We Th Fr Sa Su
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
About this blog
Zope, Python, FreeBSD, その他色々について。つまり日記か。
Categories
Agile(XP) (0)
Event (10)
Pattern (0)
その他 (10)
Zope (11)
Memo (0)
(3)
python (17)
Programming (0)
Game (0)
OO (0)
Unix (0)
WZ (0)
work (0)
Plone (11)
Windows (1)
IT-PC (4)
自転車 (0)
TurboGears (0)
ダーツ (0)
JavaScript (0)
旅行 (0)
Web (3)
セキュリティー (1)
Django (0)
LDAP (0)
データベース (0)
vi/vim/gvim (0)
C/C++ (0)
ボドゲ (0)
RoR (2)
pyspa (1)
スタトレ (0)