2014/03/27

Pixel Artsをruby on railsで書きなおしてみた - part1

さて皆さん(浜村淳)、Pixel Artsはご覧いただけたでしょうか? まぁ人によってはクッソ役に立たないコンテンツなのかも知れませんが、ソースコードを覗いてもらえば何かしら良い事があるやらないやらというサイトですが、最近再度rubyの勉強を始めまして、一通り終わった感もあったので、ベタHTMLだったPixelArtsのサイトをrailsに改修して知見を広めようと、そういう訳です。




railsをインストール

railsはrubygemsでインストールできるので、簡単です。と言いたいところですが、色々しがらみ(依存関係)があるので、すんなりとは行きませんでした。
atomicというgemのインストールでまず止まり、Development Kitのバージョン違いを解消してインストール完了。
なんか時間がかかりましたが、どうせ見ないから「--no-ri --no-rdoc」付けてインストールした方が良かったかも。
ということで、私の推奨インストールコマンドは以下の通りです。
sudo gem install rails --no-ri --no-rdoc

全く関係ないですが、このオプションをデフォルトにすることもできるので、合わせてお試しください。 → RubyGemsでgemのインストール時に--no-ri --no-rdocをデフォルトにする - アインシュタインの電話番号

ちなみにCentOSでrailsをインストールしてみた結果、エラーは出ませんでした。このPCは
[ystream@centos rails]$ ruby -v
ruby 2.1.0p0 (2013-12-25 revision 44422) [i686-linux]
[ystream@centos rails]$ gem --version
2.2.0

という環境になっていました。


railsのフレームワークを展開する

railsのフレームワーク一式を展開するには、これまたコマンド一発なので、非常にスピーディに開発が始められます。
rails new myapp

これだけでカレントディレクトリにフレームワークが展開されます。後はappディレクトリに移動してコントロールやモデルやビューを書く、といった具合。
今回、windowsでrails newしたところ、生成したファイルがSJISになっていて衝撃を受けました。
できたファイル全てのエンコードを変更するのも大変だし、中で日本語を扱わないものについてはソッとしておきます。

あと、不必要なjQueryとか邪魔なので、「-J」すると面倒がなくていいと思いました。
既にデザインが上がっている場合で、デザイナーさんが勝手にjQueryを自前で用意している時もバージョン違いで動きが怪しくなることもあるので要注意です。

後日別件でCentOSでも同様の作業をしてみたところ、「sudoしたいからパスワード教えて~」と言われました。
初回のrails newでは、ガッツリgemでインストールしますね。
ちなみにこの環境、複数のruby、gemが乗っかっている状態で勝手にgem installしてますが大丈夫なんでしょうか。rvmとかrbenvとか導入したほうがいいんだな、きっと。 → 導入しました。こちらも合わせてどうぞ


コントローラーを生成する

railsでは、コントローラーを作るのもコマンド一発。
今回はprojectsというコントローラーを使って構築していくことにします。
rails g controller projects index show
# rails generate controller projects index show でも可

ついでに対応するビューも同時に生成されます。

ここまでやって思ったのは、CakePHPと同じじゃんってこと。実はこれは逆なんですが。

トップページを移植してみる

とりあえず、app/views/projectsにあるindex.html.erb(CakePHPでいうindex.ctp)にトップページのHTMLをぶち込んでみます。が、おそらくレイアウトファイルとコンテンツファイルに分かれているんでしょうから、bodyタグの中身だけにしておきます。

viewsディレクトリにlayoutsディレクトリがあったので、その中のapplication.html.erbを開きます。
PixelArtsはどのページもほぼheadタグの中は共通なので、使いまわせると信じてトップページのヘッダとbodyタグを貼り付けます。


実際に動くか確認

rubyはWEBrickというウェブサーバーで動くので、サーバーを起動してみます。
rails s

これでサーバーが上がってきます。エラーがあると上がってこないですが、rubyのスクリプトは一文字も書いてない現状、上がらない訳がないです。
ブラウザで「localhost:3000」を開くとトップページが見えました。
コンソールに「0.0.0.0:3000」とか書いてあるから開いてしまいましたが映りませんでした。

:3000は3000番ポートを使ってサーバーを立てているということですが、これは変更可能で、
rails s -p 80

とすると80番ポートでアクセスを受け付けるようになるので、ブラウザで「localhost」と打つだけで表示されるようになります。
実際はapacheが動いている可能性もあるのでここは実行環境によりけりです。


実際の作品が置いてあるページを移植する

作品て。というツッコミはさておき、個別のページの移植に取り掛かります。
このページはほぼ単一のレイアウトでリンクするJavaScriptだけが違うような構成なので、作品ページは一つのコントローラーでまかなってしまうようにします。
なので、使うコントローラーも一つ。まずはHTMLのbodyを切って、ビューにある作品ページ用のhtml.erbファイルに貼り付けます。
レイアウトファイルはトップページと共通のものを使用します。

これでだいたいはいいんですが、タイトルとコメントの部分は作品によって違うので、この部分を動的に挿入するようにします。
DBを使うまでもないので、タイトルとコメントは定数化してどっかに放り込んでおくことにします。
なので、今回はモデルは使いません。

定数を置くところをどこにしようか悩みましたが、configディレクトリの下のinitializersにファイルを置くと、スクリプトが開始された時に読み込まれるという情報をどこかで見たので、そうしてみます。
ファイル名はズバリ「constants.rb」です。
この「スクリプトが開始された時」というのに若干ハマり、小一時間無駄に過ごしてしまう訳ですが、これについては後述します。

動的に挿入する部分は、
  • タイトル
  • headタグ内のdescription
  • コメント
  • 画面上部のナビゲーション部分
  • JSファイル、CSSファイルのリンクタグ
  • canvas下のボタン群
です。
このうち
  • タイトル
  • headタグ内のdescription
  • コメント
  • 画面上部のナビゲーション部分
  • JSファイル、CSSファイルのリンクタグ
は文字情報なので、元のHTMLからコピペしてconstants.rbで定数化しました。

ボタン群に関しては、2、3パターンあるHTMLなので、部品化して使いまわすようにします。

config/initializers/constants.rbで定数化

constants.rbで読み込まれた変数はグローバル変数っぽくなるので、コントローラだろうがビューだろうがどこでも読める変数です。今回のようなケースだと、これは楽に進みました。
一部処理の見通しを良くするために書きましたが、コントローラにはほとんど処理を書いていません。
こんな単純なサイトだと、これで十分かなと思いますね。


ルーティング

この辺がモダンなフレームワークの良さですが、URLを変えたくないので、ガリガリとルーティングしました。
ルーティングを担っているのは、configディレクトリ直下にある、routes.rbです。
素の状態だとトップページは、「http://localhost/projects/index」というURLになっていますが、「http://localhost」であってほしいので、変更します。
root to: "projects#index"

トップページの変更はこれだけです。あっけない・・・。

次は個別の作品ページのルーティングです。
これが面倒かなと思いましたが、constants.rbに書いた定数の中に作品ごとのディレクトリ名でインデックスを付けたハッシュを用意していたので、それをeachで回すだけでルーティングは完了です。このインデックスをパラメータとして付与すれば、単一のコントローラであってもパラメータで異なるページを表示できます。
ベタに書くと、作品をアップする度にroutes.ebも更新する羽目になりますので手間が省けました。
routes.rbに書いたコードは4行だけなので、全部晒してみます。
PixelartRb::Application.routes.draw do
  root to: "projects#index"
  PROJECT_NAME.each {|key, name|
    get "/" + name, to: "projects#show", id: key
  }
end

以上がroutes.rbの内容です。


ビューにrubyスクリプトを埋め込む

いよいよ佳境に差し掛かってまいりましたが、作品ページで動的に差し替える部分に変数を埋め込んでいきます。
ぱっと見分からなかったのが
<% hoge %>
<%= hoge %>

の違い。=がないと、何も表示されないのにハマりました。情けない。

調べてみると、他にも幾つか種類があるようなので、まとまったページを見て参考にしてください。 → ビュー(view) - Railsドキュメント


ビューファイルからレイアウトを変更する

変数の埋め込みは終わりましたが、作品のページごとに違うJavaScriptのソースを読み込まないといけないので、それを試します。
ビューファイルからレイアウトの一部を差し替えるということで、ビューファイルの中でcontent_forというメソッドを使ってレイアウトを変更してみます。
<% content_for :js do %>
<%= javascript_include_tag @js %>
<% end %>

これをビューファイルの先頭の方に加えました。ちなみに@jsには作品ごとのJSファイルのファイル名が入る想定です。
CSSファイルも同様の手法で切り替えができます。

後は、レイアウトの方もビューから送られてくるものを受け取る準備をします。
挿入したい箇所に一行加えるだけです。
<%= yield :js %>

content_for :jsとyield :jsが対になっている必要があります。
:jsの部分を変えれば複数設置することもできます。


ボタン群をテンプレート化する

JavaScriptのスタート/ストップボタンに幾つかバリエーションがあるので、部品化してみます。
部分的にテンプレートする際は、「_テンプレート名.html.erb」として保存します。
どこでもいいようですが、コントローラーを横断して使う場合はsharedというディレクトリをviewsの下に用意してその中に置いておくのがいいようです(諸説あり)。
今回は、単一のコントローラーでしか使わないので、他のビューファイルと同じ所に保存しました。

_default_button.html.erbを使う場合は、非常に簡単で
<%= render "default_button" %>    #アンダースコアと.html.erbを除いたファイル名

を挿入したい箇所に書くだけです。


constants.rbが反映されない

先に出てきた、constants.rbがスクリプトが開始された時に読み込まれるという件ですが、このスクリプトが開始された時というのがピンと来なかったのは、明らかにPHPのやり過ぎだと思います。

railsの場合は、コンソールから「rails s」を打ち込んだ時がスクリプトの開始した時のようです。
なので、ここをいじる場合は一度WEBrickを落とす必要があるということですね。


そして完成した

色々詰まりながらやりましたが、railsのインストールから始めて調べながら4、5時間くらいで移行は完了しました。
サイトのコンパクトさもあっての時間ですが、少ない手数でここまで来れたのはすごいですね。
CakePHPでノリが分かっていたのも大きいかと思います。
元がベタHTMLだっただけに、レスポンスが遅くなったのは否めないですが、許容範囲内ということで許してください。

やってみて、「rubyをわかってる」よりも「railsのお作法が分かってる」のほうが開発速度が速いのかなと感じました。
CakePHPからの乗り換えもスムーズですし、railsからrubyを勉強するのもアリかなと思います。

あと、Rubyに関しては、Windowsで開発するのはエンコードの問題で落とし穴がいくつもあるので、Windows環境での開発はオススメできません。あと、複数のRubyをインストールする場合はバージョン管理する環境も忘れずに:-P


主にネットワークやサーバー設定を行った続編もありんす。


0 件のコメント:

コメントを投稿