プロジェクト

全般

プロフィール

GuideRails » 履歴 » リビジョン 2

リビジョン 1 (Mitsuyoshi Yoshida, 2011/06/25 23:25) → リビジョン 2/7 (Mitsuyoshi Yoshida, 2011/06/26 00:03)


 h1. Rails の概要 

 プラグインの説明に入る前に Rails について簡単に説明しましょう。 
 まず、Rails とはなにかというと Web アプリケーションのためのフレームワークです。 


 h2. フレームワーク 

 それでは、フレームワークとは何でしょう。 
 直訳すると *枠組み* です。 Web アプリケーションに限らず、プログラムでは決まりきった処理というのはたくさんあります。この面倒な決まりきった処理をやってくれるのがフレームワークです。フレームワークを使うことによりアプリケーションの中身だけを集中して作成することが出来ます。 アプリケーションに限らず、プログラムでは決まりきった処理というのはたくさんあります。この面倒な決まりきった処理をやってくれるのがフレームワークです。フレームワークを使うことによりアプリケーションの中身にだけを集中して作成することが出来ます。 
 また、単に面倒なことの肩代わりというだけでなく、専門的な知識が必要なこともやってくれます。例えば Rails を使えばデータベースやインターネットネットのセキュリティといったことをあまりよく知らなくても Web アプリケーションを作ることができます。 
 似たようなものとしてライブラリがありますが、こちらはアプリケーションから利用するという感じなのに対してフレームワークでは枠組みにあわせてアプリケーションを作っていく感じです。 

 Redmine はこの Rails フレームワークを使って作られた Web アプリケーションです。 Redmine のプラグインを作る場合もこのフレームワークに沿って作っていく必要があります。 


 h2. MVC 構造 

 Rails フレームワークのアプリケーションは MVC(Model View Control) 構造をとっています。 

 この MVC 構造というのは    GUI アプリケーションを作る場合、こうした方がいいよ というふうに古くから言われている構成で、 GoF 本と呼ばれるデザインパターンの有名な本でも紹介されています。 
 この M, V, C が表しているものはそれぞれ次のような部分です。 

 |Model    | データを扱う部分 | 
 |View     | 表示、ユーザインターフェース部分 | 
 |Control| ユーザの入力に応答して処理する部分 | 

 ただ、 ユーザインターフェース部分とデータを扱う部分をなるべく分けたほうがいいというのは確かなのですが、普通の GUI プログラムではこの View と Control は分けるのは難しいです。このため Windows の Document-View 構造や Qt の Mode-View 構造のように V と C が一緒になっている構造の方が一般的です。 
 しかし Web アプリケーションに限って言えば、表示が html のページで、応答処理は CGI というように View と Control がはっきり分かれるので、 MVC 構造はしっかりとはまります。 
 Rails に限らず CGI を使った Web アプリでは基本的に MVC のような構造になっているとは思いますが、 Rails の場合後述する *規約* という方針のため、 Model, View, Control という言葉はふんだんに出てきます。 

 !mvc.png! 

 この MVC が Rails ではどこに相当するかについてもみていきましょう。 
 Model というのは、データを扱う部分でデータそのものではありません。 Rails でのデータはデータベースになります。そのため Rails のモデルはデータベースを扱う部分ということになります。 
 View は Web では html にあたるので、 html ファイルを生成するところです。Rails では Erb という html に埋め込まれた ruby コードを評価して html ファイル生成するライブラリを使っています。 
 ユーザはブラウザで html を見て、新規作成や一覧表示といった何らかのアクションを行います。html ではこれがリンクやフォームボタンで提供され、このユーザのアクションに Contol が対応します。例えばデータの一覧表示であれば、 Model を呼び出してデータを取得し、それを View に渡して、html を作成します。  



 h2. 設計より規約 

 Rails では 2 つの大きな方針があります。 

 * CoC (Convention Over Configuration) 
 ** 設計より規約 
 * DRY (Don't Repeat Yourself) 
 ** 繰り返しの禁止 

 まずは *設定よりも規約* という方針について説明していきます。 
 これは設定を変更できる機能をつけずに名前を決めうちにすることで、より手軽に作れるようにしようという考え方です。 

 例えば、他のプラグインをインストールしたことのある方はご存知だと思いますが、 @vender/plugins@ 以下にディレクトリをおくとそれがプラグインとして扱われます。普通ライブラリなどを追加する場合、まずロードパスを設定し、ロードファイルをロードするコードを記述する必要があります。ロードする対象となるディレクトリをあらかじめ決めておくことで、設定する手間なく簡単にプラグインを追加することが出来ます。 

 よくプログラミングではハードコーディングは良くないといわれます。ですが、実装中などで簡単にテストしたいときなど、ファイル名を決めうちで作っておいて、後で設定機能を実装するというようなことをやることも多く、やっぱり決めうちにしておくと楽なのは確かです。基本的にディレクトリ構成やファイル名などは分かりやすいように決まった名称を使うことが多いと思います。こういったものを慣習ではなく、規約とすることで決めうちの簡便さを利用することが出来ます。 
 ただ、欠点なのはこの規約のルールを知らないとソースをみただけでは流れが見えず、何をやっているのかよく分からないということがよく起こります。しかし、これも逆にルールがわかってくるとこの機能はどこで実装しているかといったことがすぐにわかり、非常にソースコードを読むのが楽になります。 


 さらにディレクトリやファイル名を決めうちにするだけでなく、 ruby のメタプログラミングを利用して自分が作ったファイルなどもロードの指定なく利用することが出来るようになります。 このメタプログラミングというのは ruby のスクリプト中で、今どのようなクラスやメソッドが知ることが出来たり、エラー処理を書き換えたりすることができる機能です。 
 例えば FooBar.new というような記述でクラスを使用したとします。通常、 定義ファイルのロードなしでは FooBar は未定義ですというようなエラーがでます。 Rails ではエラー処理を拡張し、知らないクラスを使おうとすると foo_bar.rb という名前のファイルを探してロードします。 
 この探すファイルの名前は以下のようにしてクラス名から決めます。 

 # 大文字小文字による単語の区切りを _ (アンダーバー)に変換 
 # すべて小文字に変換 
 # 拡張子を .rb にする 

 ただし、そのファイルは lib などあらかじめ決められた検索対象ディレクトリにところにおいておく必要があります。 
 また、 SomeMod::FooBar というようにモジュール内のクラスの場合は some_mod/foo_bar.rb というようにモジュール名をディレクトリとして、検索ディレクトリ以下におきます。 

 ruby ではクラス名の先頭を大文字で始めるという決まりがあるので、ruby のスクリプト内では先頭大文字で大文字小文字の変化で単語の区切りを表し、ファイル名ではアンダーバー区切りの小文字を使うというのが Rails の命名の基本です。すなわち、コード中の Pascal ケース(アッパーキャメルケース)のものはスネークケースにしたファイル名のものに対応するということです。 

 このような Rails の規約はまだいろいろありますが、出てきたときにその都度説明することにしていきます。 



 h2. 繰り返しの禁止 

 設計より規約という方針は従来のプログラミングと比べ、かなり画期的だった思いますが、こちらはプログラミングの基本とも言えます。 
 ただ、方針としてあげているだけあって、繰り返しを避けるための手段がいろいろ提供されています。私もコーディング時に同じようなことを何度も書くのが嫌いなので、この方針はとても助かっています。 

 とはいえ、規約の方はそれにあわせないと作れないのに対して、繰り返しはやろうと思えば出来てしまいます。実際、 Redmine のソースでも意外と繰り返しがあったりもします。 
 でも、やっぱり繰り返しを避けることは大切でと思います。そこで、もし同じことを 2 回書いた場合、何か避ける方法はないかなと考えてみてください。 Rails であれば大抵それは避けることができるはずです。 


 --- 

 | [[プラグイン開発ガイド|^]] | [[GuideDevEnv|<<]] | [[GuideSampleSpec|>>]] |