takoblo

コード読んだめも

rubicure

最近ちまちまこっそりコードリーディングをしてる. 自分が普段かかないような構文がみられるのは楽しい.

今回は特に目的を決めないで目についた面白そうなところから読んでみる

rubicure

All about Japanese battle heroine “Pretty Cure (Precure)”.

プリキュアruby実装. ちなみにたこはプリキュアは無印しかしらない.

よんでみる

執筆時点の最新v1.0.4をよむ.

とりあえずreadmeの一番頭を見てみる

Precure.title
#=> "ふたりはプリキュア"

Precure.unmarked.title
#=> "ふたりはプリキュア"

Precure.max_heart.title
#=> "ふたりはプリキュア Max Heart"

# ...

title メソッドとかは,yamlファイルにかかれたハッシュから引かれてるみたい.(というかキーそれぞれにメソッド生やしてたら必要以上に冗長になりそう)この辺のメソッドを定義してる部分から読んでみる.

unmarked: &unmarked
  series_name: unmarked
  title: ふたりはプリキュア
  started_date: 2004-02-01
  ended_date:   2005-01-30
  girls:
  - cure_black
  - cure_white
futari_wa_pretty_cure:
  <<: *unmarked

# ...

Precure module は method_missing がオーバーライトされてた.

module Precure
  def self.method_missing(name, *args, &block)
    Rubicure.core.send(name, *args, &block)
  end
end

Rubicure.core で method を実行させているけど,ここでも method_missing が上書きされていて, Rubicure::Series#find でハッシュの中身をもってきてる

def method_missing(name, *args)
  unmarked_precure = Rubicure::Series.find(:unmarked)

  if Rubicure::Series.valid?(name)
    Rubicure::Series.find(name)
  elsif unmarked_precure.respond_to?(name)
    unmarked_precure.send(name, *args)
  else
    super
  end
end

https://github.com/sue445/rubicure/blob/v1.0.4/lib/rubicure/core.rb#L10-L20

configyaml をロードしたハッシュを持ってきてる. https://github.com/sue445/rubicure/blob/master/lib/rubicure/series.rb#L84-L91

def find(series_name)
  raise UnknownSeriesError, "unknown series: #{series_name}" unless valid?(series_name)

  @cache ||= {}
  unless @cache[series_name]
    series_config = config[series_name] || {}
    series_config.reject! { |_k, v| v.nil? }

    @cache[series_name] = Rubicure::Series[series_config]
  end

  @cache[series_name]
end

Rubicure::Series#find

method missing のオーバーライドはびっくりした


Cureyamlからデータを引っぱってくるところまでは Series とほぼほぼ同じ

Cure.lemonade
#=> {:girl_name=>"cure_lemonade", :human_name=>"春日野うらら", :precure_name=>"キュアレモネード", :cast_name=>"伊瀬茉莉也", :created_date=>Sun, 18 Feb 2007, :color=>"yellow", :transform_message=>"プリキュア!メタモルフォーゼ!\nはじけるレモンの香り、キュアレモネード!\n希望の力と未来の光!\n華麗に羽ばたく5つの心!\nYes!プリキュア5!", :extra_names=>nil, :attack_messages=>["輝く乙女のはじける力、受けてみなさい!\nプリキュア!プリズム・チェーン!"], :transform_calls=>["metamorphose"]}

Cure.pine
#=> {:girl_name=>"cure_pine", :human_name=>"山吹祈里", :precure_name=>"キュアパイン", :cast_name=>"中川亜紀子", :created_date=>Sun, 15 Feb 2009, :color=>"yellow", :transform_message=>"チェインジ!プリキュア・ビートアップ!\nイエローハートは祈りのしるし!\nとれたてフレッシュ、キュアパイン!\nレッツプリキュア!", :extra_names=>["キュアエンジェルパイン"], :attack_messages=>["悪いの悪いの飛んでいけ!\nプリキュア!ヒーリングプレアーフレッシュ!"], :transform_calls=>["change_precure_beat_up", "change", "beat_up"]}

Cure.sunshine
#=> {:girl_name=>"cure_sunshine", :human_name=>"明堂院いつき", :precure_name=>"キュアサンシャイン", :cast_name=>"桑島法子", :created_date=>Sun, 18 Jul 2010, :color=>"yellow", :transform_message=>"(プリキュアの種、いくですぅ!)\nプリキュア!オープンマイハート!\n陽の光浴びる一輪の花! キュアサンシャイン!\nハートキャッチ、プリキュア!", :extra_names=>["スーパーキュアサンシャイン"], :attack_messages=>["花よ、舞い踊れ!\nプリキュア!ゴールドフォルテバースト!!", "花よ、咲き誇れ!\nプリキュア・ハートキャッチ・オーケストラ!!"], :transform_calls=>["open_my_heart"]}

# ...

だけど,プリキュアは変身すると攻撃できるようになる.

yayoi = Precure.smile.girls[2]

yayoi.name
#=> "黄瀬やよい"

yayoi.cast_name
#=> "金元寿子"

yayoi.attack!
#=> RuntimeError: require transform


yayoi.transform!

(レディ?)
プリキュア・スマイルチャージ!
(ゴー!ゴー!レッツ・ゴー!ピース!!)
ピカピカピカリンジャンケンポン! キュアピース!
5つの光が導く未来!
輝け!スマイルプリキュア!

# 1st transform
yayoi.name
#=> "キュアピース"

yayoi.attack!

プリキュア!ピースサンダー!!

これは素直に簡潔に書いてた

def attack!
  raise RequireTransformError, "require transform" if current_attack_message.blank?

  print_by_line current_attack_message

  current_attack_message
end

@current_state って変数に整数値で現在の状態をもたせてた.0だったら変身前,1だったら1段階変身..みたいな. これをcurrent_attack_message で変身後かどうか(@current_state が0でないか)を判定して変身の台詞を持ってきてる. print_by_line はいい感じにdelayをつけてメッセージを標準出力するやつ.

yamlには attack_messages に台詞が配列で入ってて @current_state でインデックスを指定できるようになってる.

cure_peace: &cure_peace
  # ...
  extra_names:
  - プリンセスピース
  - ウルトラピース
  attack_messages:
    - |-
      プリキュア!ピースサンダー!!
    - |-
      開け、ロイヤルクロック!
      (みんなの力を1つにするクル!)
      届け、希望の光!
      はばたけ!光り輝く未来へ!
      プリキュア!ロイヤルレインボーバースト!
    - |-
      (みんなの力を1つにするクル!)
      プリキュア!ミラクルレインボーバースト!
      輝けー!!
      スマイルプリキュア!!
  transform_calls:
    - smile_charge

raise RequireTransformError, "require transform" がかっこいい. lib/rubicure/errors.rb で定義してる

transform!, name もおなじように @current_state でひっぱってきてる

maho_girls だけは transform_styles ってのがあって,それぞれに girl_name, human_name … てのがあるらしく,それは define_method で定義されてた.

https://github.com/sue445/rubicure/blob/v1.0.4/lib/rubicure/girl.rb#L95-L103

まなび

かんそう

最新シリーズのアラモードってやつのyamlが美味しそうで夜中に読んでたら無限にお腹がへったのがつらかった. コードは思ってたほどメタプロじゃなかった.ここ最近読んだ中では難易度的にも一番読みやすかった.

REF

rubicure: All about Japanese battle heroine “Pretty Cure (Precure)”