ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

SinatraのシステムをPadrinoへ移行してみた

※本記事は自鯖Blogの転載です
※元記事は2012/06/25に書かれました

http://blog.parrot-studio.com/2012/06/sinatra-to-padrino/

※この記事の内容はすでに古く、現在はPadrinoからさらにRails4へ移行しております
 ですが、過去の経緯を残す意味で、(自分自身のために)記事を残します



仕事でもプライベートでも使いまくっていたRubySinatraですが、
そのシンプルな設計思想ゆえに、ある程度複雑化すると、
ルーティングが管理しきれなかったり、ディレクトリ構造に迷ったりします(´-ω-)

次の仕事でもSinatraを使うつもりでいたのですが、
規模を考えるとちょっとリスキーであり、
かといってRailsでは重すぎるので、どうしたものかと

そこで目をつけたのが、「Sinatra以上Rails未満」といわれるフレームワーク
「Padrino」でございます(`・ω・´)

http://jp.padrinorb.com/

Sinatraをベースに、いろいろなモジュールを自由に付け加えることで、
Sinatraでは難しかった構造化が楽になるのですが、
それを調べていたところ・・・

WEB+DB PRESS Vol.69

WEB+DB PRESS Vol.69

  • 作者: 大塚弘記,渡辺修司,堤智代,森田創,中島聡,A-Listers,はまちや2,川添貴生,井上誠一郎,近藤宇智朗,ヒノケン,後藤秀宣,佐藤鉄平,mala,奥野幹也,伊藤智章,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2012/06/23
  • メディア: 大型本
  • 購入: 13人 クリック: 143回
  • この商品を含むブログ (18件) を見る

・・・今月のWEB+DB PRESSにPadrinoの記事がΣ(・ω・ノ)ノ

今回はこの記事より前にPadrinoを調査していたのですが、
記事で言及されていた方向性と私の認識に大きなずれはないようなので、
次の仕事はPadrinoでいこうかと

とはいえ、Padrinoをいきなり仕事に投入するのはリスキーです
特に、表面的な事例をあまり聞かないだけに・・・


例によって前置きが長くなりましたが、
今回はROのGv戦況確認システム「ROGv」を、
SinatraからPadrinoに移行したというお話

現時点ではテスト中なので、
Padrino版のコードはGithubにありませんが、
とりあえずSinatra版のコードを(´・ω・)っ

https://github.com/parrot-studio/rogv_server

<2012/06/26追記>
GithubのmasterにPadrino版をpushしました
Sinatra版はv1.xのbranchにあります

https://github.com/parrot-studio/rogv_server/tree/v1.x
</追記>

本番にはまだ適用してませんが、
サンプルサイトはすでにPadrino版で動いています

http://parrot-studio.com/rogvs/

<2013/07/18追記>
現在はRails4版に移行しています

https://github.com/parrot-studio/gagnrath

http://ro.parrot-studio.com/rogvs/
</追記>

PadrinoとSinatraの違い


PadrinoはSinatraの上位互換・・・と言いたいところですが、
細かいところでいろいろあります(´-ω-)
とりあえずは「Sinatraをいろいろなモジュールで拡張したもの」と考えてOKです

どんなモジュールがあるのかはこちらを

http://jp.padrinorb.com/guides

SinatraにPadrinoのモジュールを適用する方法はこちら

http://jp.padrinorb.com/guides/standalone-usage-in-sinatra


Sinatraへのモジュール組み込み(・・・に失敗)


これを見て、「既存のSinatraアプリを拡張できるのでは!?」と思いまして、
ちょうど欲しかった「Cacheモジュール」を追加してみることに

元々、ROGvの初期版はデータをmemcachedとファイルに保存していて、
MongoDBに移行したときにmemcachedをやめてしまっていたのですが、
いくらMongoDBが速いといっても、やはりCacheの仕組みはいるだろうと

そこで、先ほどのガイドに従い、
「register Padrino::Cache」してみたわけですが、
全く動きませんΣ(゚Д゚)ガーン

エラーメッセージやPadrino::Cacheのコードを読んでみたところ、
Padrino::Cacheは「Padrino::Routing」にもろに依存しており、
Padrino::Cacheだけ入れるのは少々面倒と判明

Padrino基盤への移植


Sinatraの肝はシンプルなルーティング記述であり、
Padrinoがそこを拡張しているのであれば、
もうPadrinoベースで書いた方が早いのではないかと

ROGvは比較的ルーティング内のコードを小さくしてあったので、
Padrinoのルーティングに移植するコストは小さいだろう、
という目論見もありました

というわけで、新しくPadrinoの基盤を作りまして、
そこにSinatra版のコードを「ほぼコピペ」していく感じで移植をΣ(・ω・ノ)ノ

というのも、元々Sinatra版はRailsとかのコードを意識していて、
それっぽいhelper等を定義していたのですが、
PadrinoはHelperモジュールとしてそれを持っていたからです

さらに、ある程度RESTfulに設計し、構造化してあったので、
ルーティングの書き方が少々変わったところで、
「中身」は完全にコピペでOKだったのです

なので、View等のコード変更は最小限で済み、
半日かからず移行完了しました∠( ゚д゚)/

ただし、「controller」のところで少々はまりました

Padrinoのcontrollerは「ブロック」なので、
Sinatraの感覚で「中」に共通メソッドを切ったところ、
「メソッドがねぇぞ!(#゚Д゚)」と怒られました

このあたりはRailsとも違うところなので、
私はこの違いに気づかず、かなり時間を無駄にしたのですが、
とりあえず共通メソッドはapp.rbのアプリ本体内に定義しましょう*1




というわけで、今回はSinatraをPadrinoに移行してみたわけですが、
Sinatraでは苦しい、ある程度の規模」になった場合、
Padrinoへの移行検討をお勧めします

なんだかんだでRailsは完全であるがゆえに遅いので、
特にAPIのような仕組みを作る場合、
Sinatraの方が速くて書きやすいですし、私もそうしてきました

しかし、ある程度構造化が必要になる規模だと、
とたんにSinatraのシンプルさが問題になってきて、
結局Railsにあるようなメソッドを自分で書くはめになるはずです

そういった流れでPadrinoが出てきたのは自然なことで、
今回のROGvでも同じようなことを考えていたからこそ、
設計思想が一致し、楽にいけたのだと思います(`・ω・´)

もちろん、PadrinoはSinatraに比べてシンプルさに欠けるので、
単純にSinatraを置き換えるべき、とはこれっぽっちも思いません
同様に、Railsが不要とも全く思いません

Sinatra/Padrino/Railsの「見ている先」を把握した上で、
作ろうとしているもの合うのを選ぶのがいいと思いますし、
そういった選択が可能なのがRubyのいいところかなと(`・ω・´) b

*1: 今回の場合、Padrinoのbeforeフィルターを使う方がいいし、そのためのcontrollerなのですが、とにかくまず移植完了させることを優先させました リファクタリングは動いてからやらないと、原因が把握できなくなりますし・・・