このチュートリアルでは、OracleとRuby/Railsのインストールと非常に効率的で機能的なRuby/Railsアプリケーションの開発方法について説明します。 Ruby/Railsを使用した強力なエンタープライズ・アプリケーションを作成するために必要な知識を習得できます。
約1時間
Ruby on Railsは、速度を向上させてデータベース・ドリブンなWebサイトの作成を簡素化する無償のWebアプリケーション・フレームワークです。最初からスケルトン・コード・フレームワーク(足場)が提供されています。 一般的にRailsまたはRoRと呼ばれるRuby on Railsは、Rubyプログラミング言語で記述されたオープンソース・プロジェクトです。Railsフレームワークを使用したアプリケーションは、Model-View-Controller(MVC)設計パターンで開発されます。
RoRは、J2EEおよびPHPプログラマーの間で非常に注目を集めています。 RoRの長所を検討すると、J2EEおよびPHPプログラマーが注目する理由が分かります。 たとえば、設計パターンの専門家が賞賛する厳密なModel-View-Controllerアーキテクチャを使用する点は、J2EE開発者にとって魅力的です。 また、Railsを使用した基本システムの構築の容易さは、PHP開発者にとって魅力的です。
RoRは、MVCの効果的なソリューションを提供します。 モデルは、データだけではありません。データに適用されるすべてのビジネス・ルールを施行します。 モデルは、ゲートキーパーおよびデータ・ストアとして機能します。 ビューでは、モデルのデータに基づくユーザー・インタフェースの作成を管理します。 ビューではユーザーによるさまざまなデータ入力を実行できますが、ビュー自体は入力データを処理しません。 ビューの機能は、データ表示のみです。 コントローラは、外部(通常、ユーザー入力)からイベントを受信し、モデルとやり取りして、ユーザーに適切なビューを表示します。
RoRは、オブジェクト・リレーショナル・マッピング(ORM)層としてActiveRecordを提供し、データベースの接続とデータの操作を行います。 ActiveRecordは、標準のORMモデル(表とクラス、行とオブジェクト、列とオブジェクト属性)に厳密に準拠します。
Railsアプリケーションが作成されると、ルートの下に次のディレクトリとファイルが作成されます。 app, components, config, db, doc, lib, log, public, Rakefile, README, script, test, tmp, vendor
Rubyは、簡易性と生産性に注目した動的なオープンソースのプログラミング言語です。 読みやすく書きやすい、優れた構文が提供されます。 Ruby言語の詳細は、付録:Ruby入門を参照してください。
詳細情報を取得するには、Ruby on Rails OTNフォーラムを参照してください。
この項で使用するコマンドは、以下のとおりです。
OCI8.new (userid, password, dbname = nil, privilege = nil): |
ユーザーIDおよびパスワードでOracleに接続します。 dbnameは、Net8の接続文字列です。 DBA権限が必要な場合、SYSDBAまたはSYSOPER権限を設定してください。
|
|
OCI8#logoff |
Oracleの接続を解除します。 コミットされていないトランザクションはロールバックされます。 |
|
OCIError | Oracleエラー・コードを使用した例外クラスです。 OCIError#messageによるエラー・メッセージとOCIError#codeによるエラー・コードを取得できます。 |
Rubyスクリプトの作成タスクでは、最初にデータベースの接続を作成します。 以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してconnect.rbを実行します。 export NLS_LANG=American_America.UTF8 ruby connect.rb 接続に成功すると、上記のメッセージが表示されます。接続に失敗すると、エラーが表示されます。 connect.rbファイルの内容は、次のとおりです。 # connect.rb: Create connections to Oracle
|
---|---|
2 . |
このチュートリアルの残りのスクリプトに含まれるコマンドは、以下のとおりです。 require 'config.rb'
|
この項で使用するコマンドは、以下のとおりです。
OCI8#parse (sql) |
カーソルを作成し、SQL文の実行を準備して、OCI8::Cursorインスタンスを返します。 |
|
OCI8#exec (sql, *bindvars) |
SQL文を実行します。 戻り値のタイプは、SQL文のタイプによって異なります。 bindvarsを指定すると、実行前にバインド変数としてバインドされます。 |
|
OCI8::Cursor#exec(*bindvars) | カーソルに割り当てられたSQL文を実行します。 戻り値のタイプは、SQL文のタイプによって異なります。 | |
OCI8::Cursor#getColNames | 選択リストの名前を配列で取得します。 exec後にこのメソッドを使用してください。 |
簡単な問合せを作成して結果を表示するには、以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してfetch.rbスクリプトを実行します。 ruby fetch.rb 出力のスクリーンショットは、以下のとおりです。 fetch.rbファイルの内容は、次のとおりです。 #fetch.rb: Fetch data from database
|
---|---|
2 . |
Rubyに固有のコードを記述する別の方法があります。 ターミナル・ウィンドウから、次のコマンドを実行してfetch_r.rbスクリプトを実行します。 ruby fetch_r.rb 出力のスクリーンショットは、以下のとおりです。
fetch_r.rbファイルの内容は、次のとおりです。 # fetch_r.rb: Fetch in a more ruby-like way
|
3 . |
フェッチされる行数が多い場合、プリフェッチを使用するとパフォーマンスが向上します。 ターミナル・ウィンドウから、次のコマンドを実行してprefetch.rbスクリプトを実行します。 ruby prefetch.rb 出力のスクリーンショットは、以下のとおりです。
prefetch.rbファイルの内容は、次のとおりです。 # prefetch.rb: Prefetch data
|
バインド変数を使用すると、コードの再利用性が向上し、SQLインジェクション攻撃のリスクがなくなります。 この項で使用するコマンドは、以下のとおりです。
OCI8::Cursor#bind_param(key, val, type = nil, length = nil) |
明示的なバインド変数。 キーが数値の場合、1で始まる位置によってバインドされます。 キーが文字列の場合、プレースホルダの名前でバインドされます。 |
|
OCI8#exec (sql, *bindvars) or OCI8::Cursor#exec(*bindvars) |
bindvarsで変数をバインドすることもできます。 |
|
OCI8::Cursor#[key] | バインド変数の値を取得/設定します。 |
この例でバインド変数を使用するには、以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してbind.rbスクリプトを実行します。 ruby bind.rb 出力のスクリーンショットは、以下のとおりです。 bind.rbファイルの内容は、次のとおりです。 # bind.rb: How to bind variables
|
---|---|
2 . |
バインド変数を使用してパフォーマンスの向上をテストするには、次のコマンドを実行してbind_perf_test.rbスクリプトを実行します。 ruby bind_perf_test.rb 出力のスクリーンショットは、以下のとおりです。
bind_perf_test.rbファイルの内容は、次のとおりです。 # bind_perf_test.rb: Performance test for binding variables
|
この項で使用するコマンドは、以下のとおりです。
OCI8::Cursor#define(pos, type, length = nil) |
parseおよびexec内でこのメソッドを使用します。 posは1から開始されます。 タイプが文字列の場合に長さが使用されます。 |
フェッチした値のデータ型を明示的に示すことができます。 この例でデータ型を定義するには、以下の手順に従います。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してdefine.rbスクリプトを実行します。 ruby define.rb 出力のスクリーンショットは、以下のとおりです。 2つのブロック出力の違いを確認できます。 define.rbファイルの内容は、次のとおりです。 # define.rb: Define output columns require 'config.rb' # Create a connection to Oracle conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER) # Prepare the data conn.exec("DELETE FROM test_define"); conn.exec("INSERT INTO test_define VALUES(1,'Scott Tiger', SYSDATE, SYSTIMESTAMP)") # Define to fetch Date and Time cursor = conn.parse("SELECT name,birthdate,lastvisit FROM test_define WHERE id = :id") cursor.bind_param(1, 1) cursor.define(1, String, 100) cursor.define(2, Date) cursor.define(3, Time) cursor.exec while r = cursor.fetch puts r.join("\n") end puts # Define to fetch Date and Time as String #conn.exec("ALTER SESSION SET nls_territory='TAIWAN' nls_language='TRADITIONAL CHINESE'") cursor = conn.parse("SELECT name,birthdate,lastvisit FROM test_define WHERE id = :id") cursor.bind_param(1, 1) cursor.define(1, String, 100) cursor.define(2, String, 100) cursor.define(3, String, 100) cursor.exec while r = cursor.fetch puts r.join("\n") end conn.logoff puts '-'*80
|
---|
Oracleデータベースのデータを操作する場合(データの挿入、更新、または削除)、変更されたデータや新しいデータは、データベースにコミットされるまでデータベース・セッション内でのみ使用できます。 変更されたデータがデータベースにコミットされた後は、他のユーザーおよびセッションでも使用できます。 これがデータベース・トランザクションです。
各変更を個別にコミットすると、サーバーに余分なロードが発生します。 通常、コミットされたデータをすべて使用するかまったく使用しないかのいずれかです。独自のトランザクション制御には、パフォーマンスとデータ整合性の利点があります。
この項で使用するコマンドは、以下のとおりです。
OCI8#autocommit |
autocommitモードの状態を取得/設定します。 デフォルト値はfalseです(ログオフ時にコミットされていないトランザクションがロールバックされるので注意してください)。 trueの場合、insert/update/delete文を実行するたびにトランザクションが自動的にコミットされます。 |
|
OCI8#commit() | トランザクションをコミットします。 | |
OCI8#rollback() | トランザクションをロールバックします。 |
トランザクションの管理方法を学習するには、以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してtransaction.rbスクリプトを実行します。 ruby transaction.rb このスクリプトは、conn1接続を使用して行を更新します。 Oracleの新しいデータは、コミットされるまで元のデータベース・セッションにのみ表示されます。 出力のスクリーンショットは、以下のとおりです。 この場合、conn2接続は、conn1のコミットされていないトランザクションで発生した内容を認識していません。 transaction.rbファイルの内容は、次のとおりです。 # transaction.rb: How to use transactions
|
---|---|
2 . |
transaction.rbスクリプトを更新し、conn1.autocommit = trueをコメントアウトして、ファイルを保存します。 次のコマンドを使用して、スクリプトを再実行します。 ruby transaction.rb conn2が新しい内容を認識します。 出力のスクリーンショットは、以下のとおりです。
|
3 . |
各行を個別にコミットすると、サーバーに余分なロードが発生します。 各行で個別にコミットする場合とトランザクションの最後にコミットする場合のパフォーマンスの違いを比較できます。 違いをテストするには、次のコマンドを使用してtrans_perf_test.rbスクリプトを実行します。 ruby trans_perf_test.rb 2つ目の数値が1つ目の数値より小さいことを確認します。 出力のスクリーンショットは、以下のとおりです。 trans_perf_test.rbファイルの内容は、次のとおりです。 # trans_perf_test.rb: Performance test for transactions
|
PL/SQLは、SQLを拡張したOracleの手続き型言語です。 PL/SQLストアド・プロシージャおよびストアド・ファンクションがデータベースに格納されるため、迅速なアクセスが実現します。 PL/SQLストアド・プロシージャを使用すると、アプリケーションのデータベースへのアクセス方法に関係なく、すべてのデータベース・アプリケーションでロジックを再利用できます。 データをプログラム(Rubyなど)に抽出して処理するよりも速く、多くのデータ関連操作をPL/SQLで実行できます。
この項で使用するコマンドは、以下のとおりです。
DBMS_UTILITYおよびDBMS_OUTPUT |
Oracleストアド・パッケージ。 TO_CHARは、組込み関数です。 |
RubyスクリプトでPL/SQLプロシージャおよびファンクションを呼び出すには、以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してplsql.rbスクリプトを実行します。 ruby plsql.rb 出力のスクリーンショットは、以下のとおりです。 plsql.rbファイルの内容は、次のとおりです。 # plsql.rb: Call PL/SQL procedures and functions
|
---|
Oracleキャラクタ・ラージ・オブジェクト(CLOB)およびバイナリ・ラージ・オブジェクト(BLOB)列(およびPL/SQL変数)には、大量(ギガバイト)の文字とバイナリ・データを格納できます。 この項で使用するコマンドは、以下のとおりです。
OCI8::BLOB#available |
BLOBを使用できるかどうか確認します。 BLOBを使用するには、最初にEMPTY_BLOB()を挿入する必要があります。 |
|
OCI8::BLOB#read(size = nil) | BLOBから最大サイズのバイトで読み取ります。サイズが省略される場合はファイルの最後まで読み取ります。 | |
OCI8::BLOB#write(string) | 特定の文字列をBLOBに書き込みます。 |
小さいアプリケーションを作成してデータベースにイメージをロードして表示するには、以下の手順を実行します。
1 . |
PNGファイルは、スクリプト・ファイルと同じフォルダにあります。 downloadというフォルダを作成します。 ターミナル・ウィンドウから、次のコマンドを実行してblob.rbスクリプトを実行します。 mkdir download 出力のスクリーンショットは、以下のとおりです。 blob.rbファイルの内容は、次のとおりです。 #blob.rb: Save and Load BLOB
|
---|---|
1 . |
ruby.pngファイルに対する権限を確認します。 次のコマンドを実行します。 ls -l ruby.png download/ruby.png
|
Oracleデータベースのすべてのエディションには、"XML DB"が含まれます。 このテストでは、OracleからRubyにXMLデータを返す基本事項を説明します。 この項で使用するコマンドは、以下のとおりです。
DBMS_XMLGEN.getxml (statement) |
SELECT文に基づいて、リレーショナル・データからXMLを作成します。 CLOBが返されます。 |
Oracleの基本的なXML機能を学習するには、以下の手順を実行します。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してxml.rbスクリプトを実行します。 ruby xml.rb 出力のスクリーンショットは、以下のとおりです。 xml.rbファイルの内容は、次のとおりです。 # xml.rb: Generate a xml document based on relational data
|
---|
ActiveRecordは、ビジネス・オブジェクトとデータベース表に接続して、単一のラッピングでロジックとデータを表す永続的なドメイン・モデルを作成します。 これは、オブジェクト・リレーショナル・マッピング(ORM)設計パターンの実装です。 この例でActiveRecordを使用するには、以下の手順に従います。
1 . |
ターミナル・ウィンドウから、次のコマンドを実行してactiverecord.rbスクリプトを実行します。 ruby activerecord.rb 出力のスクリーンショットは、以下のとおりです。 activerecord.rbファイルの内容は、次のとおりです。 # activerecord.rb: Using ActiveRecord, the ORM module
|
---|
このチュートリアルの後半では、以下の用語を使用します。
Rake | 他のRubyプログラムを作成するRubyプログラム。 Railsでは、Rakeを使用してdb:migrate、db:schema:dump、db:schema:load、db:test:prepare、db:test:purgeなどの一連のタスクを実行します。 一般的なLinux makeツールと範囲および目的が似ています。 |
モデル | アプリケーション内の重要オブジェクトを表すRubyクラスであり、ActiveRecordのORMを介してデータベース表に関連付けられています。 |
移行 | 開発者は、データ記述言語(DDL)の代わりにRubyでデータベース・オブジェクトを作成、変更、および削除できます。 |
足場 | ActiveRecordクラスによって反映されるエントリを作成、編集、参照、削除できるデータの簡単なインタフェースを提供します。 足場が作成されると、そこにはコントローラ・ファイル(アプリケーション・ユーザーが次に移動するページを決定する)とビュー・ファイル(アプリケーション・ユーザーが参照するページをレンダリングする)が含まれます。 |
移行と足場を使用してRailsアプリケーションを作成するには、以下の手順を実行します。
1 . |
holappというもっとも基本的なRailsアプリケーションを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 rails holapp
|
---|---|
2 . |
config/database.ymlファイルのdevelopmentセクションを次の内容に置き換えて、ファイルを保存して閉じます。 development:
|
3 . |
comicモデルを作成できます。 ターミナル・ウィンドウから、次のコマンドを実行します。 ruby script/generate model comic
|
4 . |
作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit db/migrate/*_create_comics.rb
|
5 . |
self.upセクションを次の内容に置き換えて、ファイルを保存して閉じます。 def self.up
|
6 . |
データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。 rake db:migrate
|
7 . |
次のコマンドを使用して、comicモデルの足場を作成できます。 ruby script/generate scaffold --skip-migration comic name:string description:string price:float
|
8 . |
Webrickは、サーブレットを使用して機能を拡張するRubyで記述されたHTTPサーバー・ライブラリです。 次のコマンドを使用して、Webrickサーバーを起動できます。 ruby script/server
|
9 . |
アプリケーションを表示できます。 ブラウザ・ウィンドウを開いて、次のURLを入力します。 アプリケーションが正しく動作することを確認するために「New comic」をクリックして、レコードを作成します。 http://localhost:3000/comics コミック情報を入力し、「Create」をクリックします。 コミックが正しく作成されました。 「Back」をクリックします。
|
10 . |
コミックをもう1つ作成します。 「New comic」を選択します。 コミック情報を入力し、「Create」をクリックします。 もう1つのコミックが正しく作成されました。 「Back」をクリックします。
|
11 . |
両方のコミックが表示されています。 ここで、編集を実行することもできます。最初のコミックに対して「Edit」をクリックします。 何らかの情報を変更し、「Update」をクリックします。 コミックが更新されました。 「Back」をクリックします。
|
12 . |
コミックを破棄することもできます。 いずれかのコミックに対して、「Destroy」を選択します。 「OK」をクリックして確認します。 コミックが更新されました。 「Back」をクリックします。
|
13 . |
スクリプト・サーバーを停止します。 サーバーが実行されているウィンドウで、[Ctrl]を押しながら[C]を押します。
|
この項では、さまざまなデータ関係をモデル化し、これらのモデルに対してRailsでアプリケーションを構築する方法について説明します。 ここでは、記事および著者のデータベースを維持するアプリケーションを作成することで、その方法を学習します。
まず、著者と記事を入力できるアプリケーションを作成します。 その他に、フォームを変更して、記事の入力時に著者リストをポップアップ表示し、ListingページとShowページで記事の著者を表示します。 ここでは、このアプリケーションに対して、表と表の間に1対1関係を定義します。 以下の手順を実行します。
1 . |
別のターミナル・ウィンドウを開いて、次のコマンドを実行します。 cd /home/rubyhol/holapp
|
---|---|
2 . |
著者用モデルを含む足場を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 ruby script/generate scaffold author name:string vocation:string
|
3 . |
記事用モデルを含む足場を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 ruby script/generate scaffold article title:string author_id:integer abstract:text
|
4 . |
次に、記事モデルと著者モデルの関係をRailsに伝える必要があります。 そのため、生成済みのモデル・スクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/models/author.rb
|
5 . |
ファイルの内容を以下に置き換えて、ファイルを保存して閉じます。 class Author < ActiveRecord::Base
|
6 . |
作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/models/article.rb
|
7 . |
ファイルの内容を以下に置き換えて、ファイルを保存して閉じます。 class Article < ActiveRecord::Base
|
8 . |
データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。 rake db:migrate
|
9 . |
ターミナル・ウィンドウから、次のコマンドを実行してスクリプト・サーバーを再起動します。 script/server &
|
10 . |
アプリケーションを表示できます。 ブラウザ・ウィンドウを開いて次のURLを入力し、「New author」を選択します。 http://localhost:3000/authors 新しい著者を入力し、「Create」をクリックします。 著者が正しく作成されました。 「Back」をクリックします。
|
11 . |
著者をもう1人作成します。 「New author」を選択します。 もう1人の著者を入力し、「Create」をクリックします。 著者が正しく作成されました。 「Back」をクリックします。 追加した著者のリストが表示されます。
|
12 . |
次に、記事をいくつか作成します。 次のURLを入力して、「New article」を選択します。 http://localhost:3000/articles タイトルと要約を入力し、著者としてJulia Childを指定します。 次に、「Create」をクリックします。 記事が正しく作成されました。 Author: 0と表示されていることに注意してください。 これは、author_idに無効な値が設定されているために、"Julia Child"が0に変更されているためです。 次の項では、新規フォームと編集フォームを修正して、名前を表示したポップアップ・リストから著者を選択すると、コードにauthor_idが返されるようにします。
|
ここでは、生成されたフォームを修正して、記事を作成する際に著者フィールドがポップアップ表示されるようにします。 また、ListingページとShowページを修正して、著者が正しく表示されるようにします。 以下の手順を実行します。
13 . |
新しいターミナル・ウィンドウで、次のコマンドを入力します(先ほどのウィンドウではスクリプト・サーバーが実行されているため)。 cd holapp gedit app/views/articles/new.html.erb 次の行を <%= f.text_field :author_id %> 以下のとおりに変更します。 <%= f.collection_select(:author_id, Author.all, :id, :name) %>
ファイルは、以下のようになります。
|
---|---|
14 . |
articlesディレクトリのedit.html.erbファイルに対しても、同じ変更を行います。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/edit.html.erb
|
15 . |
次の行を <%= f.text_field :author_id %> 以下のとおりに変更します。 <%= f.collection_select(:author_id, Author.all, :id, :name) %>
ファイルは、以下のようになります。
|
16 . |
再度、次のURLを入力します。 先ほど作成した記事がリストに表示されていることを確認します。 「Edit」を選択します。 http://localhost:3000/articles 選択リストから著者を選択できるようになっています。 「Julia Child」を選択します。 次に、「Update」をクリックします。 記事が正しく更新されました。 Author: 1と表示されていることに注意してください。 これは、author_idの値です。 この値を名前に変更できます。
|
17 . |
articlesディレクトリにあるindex.html.erbファイルを変更します。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/index.html.erb
|
18 . |
次の行を <td><%=h article.author_id %></td> 以下のとおりに変更します。 <td><%=h article.author.name %></td>
ファイルは、以下のようになります。
|
19 . |
articlesディレクトリのedit.html.erbファイルに対しても、同じ変更を行います。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/show.html.erb
|
20 . |
次の行を <%=h article.author_id %> 以下のとおりに変更します。 <%=h article.author.name %>
ファイルは、以下のようになります。
|
21 . |
再度、次のURLを入力します。 リストに著者が表示されていることを確認します。 「Show」を選択します。 http://localhost:3000/articles Showモードですべての情報を確認できるようになりました。
|
ここでは、1人の著者が複数記事を作成できるようにします。 これにより、Authors表とArticles表の関係が1対多関係に変わります。 以下の手順を実行します。
1 . |
この関係を表示するには、author.rbファイルを変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/models/author.rb
|
---|---|
2 . |
次の行を has_one : article 以下のとおりに変更します。 has_many : articles
|
3 . |
再度次のURLを入力して、「New article」を選択します。 http://localhost:3000/articles 新しい記事を作成します。 著者として「Julia Child」を選択し、「Create」をクリックします。 記事が正しく作成されました。 「Back」をクリックします。 両方の記事が表示されています。
|
複数の著者が共同で1つの記事を作成できるようにします。 これにより、Authors表とArticles表の関係が多対多関係に変わります。 以下の手順を実行します。
1 . |
再度、authors.rbファイル内の関係を変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/models/author.rb
|
---|---|
2 . |
次の行を has_many :articles 以下のとおりに変更します。 has_and_belongs_to_many :articles
|
3 . |
article.rbファイルも変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/models/article.rb
|
4 . |
次の行を belongs_to :author 以下のとおりに変更します。 has_and_belongs_to_many :authors
|
5 . |
AuthorsとArticlesの間に結合表を作成する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。 script/generate migration CreateArticlesAuthors
|
6 . |
次に、先ほど作成したファイルを更新して、著者と記事を格納するための表を作成する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit db/migrate/*_create_articles_authors.rb
|
7 . |
次の行を def self.up end def self.down end 以下のとおりに変更します。 def self.up create_table :articles_authors, :id => false do |t| t.integer :author_id t.integer :article_id t.timestamps end end def self.down drop_table :articles_authors end
|
8 . |
データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。 rake db:migrate
|
9 . |
再度、次のURLを入力します。 エラーが発生したことを確認します。 http://localhost:3000/articles
|
10 . |
多対多関係が作成されたことで、Articleモデルに定義されたメソッド名は、authorとauthor_idからauthorsとauthor_idsに変更されました。 エラーを修正するには、new.html.erbファイルで、先ほど作成したポップアップ・リストと表示フィールドを作成および編集して、複数の著者に対応できるようにする必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/new.html.erb
|
11 . |
次の行を <%= f.collection_select(:author_id, Author.all, :id, :name) %> 以下のとおりに変更します。 <%= f.collection_select(:author_ids, Author.all, :id, :name, {},
{:multiple => :multiple} ) %>
ファイルは、以下のようになります。
|
12 . |
また、articlesディレクトリにあるedit.html.erbファイルを変更する必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/edit.html.erb
|
13 . |
次の行を <%= f.collection_select(:author_id, Author.all, :id, :name) %> 以下のとおりに変更します。 <%= f.collection_select(:author_ids, Author.all, :id, :name, {},
{:multiple => :multiple} ) %>
ファイルは、以下のようになります。
|
14 . |
また、articlesディレクトリにあるindex.html.erbファイルを変更する必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/index.html.erb
|
15 . |
次の行を <th>Author</th> 以下のとおりに変更します。 <th>Authors</th>
すべての著者名を取得して、結合(連結)する必要があります。 次の行を <td><%=h article.author.name %></td>
以下のとおりに変更します。 <td><%=h article.authors.map {|auth| auth.name}.join(", ") %></td>
ファイルは、以下のようになります。
|
16 . |
最後に、articlesディレクトリにあるshow.html.erbファイルを変更します。 ターミナル・ウィンドウに次のコマンドを入力します。 gedit app/views/articles/show.html.erb
|
17 . |
次の行を <b>Author: </b> <%=h article.author.name %> 以下のとおりに変更します。 <b>Authors: </b>
<%=h article.authors.map {|auth| auth.name}.join(", ") %>
ファイルは、以下のようになります。
|
18 . |
再度、次のURLを入力します。 リストに著者が表示されていないことを確認します。 これは、表示が切り替えられたためです。 この問題は、articles表からarticles_authors表へデータを移行することで解決できます。 ここではその代わりに、アプリケーションを使用してデータを追加します。 Boning a Duckという記事に対して、「Edit」リンクを選択します。 http://localhost:3000/articles 著者として「Julia Child」を選択し、「Update」をクリックします。 この選択リストでは、1人だけでなく複数の著者を選択できる点に注意してください。 記事が正しく更新されました。 「Back」をクリックします。 The Importance of Butterという記事に対して、「Edit」リンクを選択します。 [Ctrl]を押しながら両方の著者を選択し、「Update」をクリックします。 記事が正しく更新されました。 「Back」をクリックします。 1つの記事に対して複数の著者が表示されるようになりました。
|
AJAXの概念は、ほとんど"通常の"アプリケーション並みの高機能なブラウザを持つことにあります。 インタラクティブなページを作成して、ウィンドウを再描画することなく、サーバーから更新データを取得することができます。
たとえば、最初は作成中であったものが後で完成記事となる場合もあるでしょう。 ここでは、未完成記事のリストを常に表示する必要があるとします。 1つの記事に完成のマークを付けたら、ページ全体を再描画しなくてもリストが更新されるようにする必要があります。
AJAXを使用する前に、非AJAXの"未完成"リストから開始するともっとも簡単です。 記事が完成しているかどうかを把握できるように、データベース表を更新する必要があります。 記事は未完成の状態から始まり、完成マークを付けるためのボタンが表示されます。 容易にアクセスできるようにするため、レイアウト内に未完成記事のリストを作成します。 以下の手順を実行します。
1 . |
is_finishedというブール列を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 script/generate migration AddIsFinishedToArticle is_finished:boolean
|
---|---|
2 . |
次に、既存記事に未完成マークを付けます。 ターミナル・ウィンドウから、次のコマンドを実行します。 gedit db/migrate/*_add_is_finished_to_article.rb
|
3 . |
次の行を add_column :articles, :is_finished, :boolean 以下のとおりに変更します。 add_column :articles, :is_finished, :boolean, :default => false Article.reset_column_information Article.find(:all).each do |a| a.is_finished = false end
|
4 . |
データベースを更新します。 ターミナル・ウィンドウで次のコマンドを入力します。 rake db:migrate
|
5 . |
新しいmark_finishedアクションを呼び出す"Mark Finished"ボタンを追加します。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit app/views/articles/show.html.erb
|
6 . |
<%= link_to 'Back', articles_path %>の後に、次の行を追加します。 <%= button_to "Mark Finished", :action => :mark_finished, :id => @article.id %>
|
7 . |
レイアウトを更新して、未完成記事へのリンクを表示します。 このコードは、メインのレイアウトから分離しておく必要があります。 新しい"部分テンプレート"(フル・テンプレートではないことを示す"_"(アンダースコア)文字が先頭に付きます)を作成します。 このテンプレートはis_finishedがfalseである記事を検索し、これらに対するリンクを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 gedit app/views/articles/_unfinished.html.erb
|
8 . |
ファイルに次のコードを追加します。 <div class="unfinished-title">Unfinished Articles</div>
|
9 . |
次に、既存のレイアウトから新しい"部分テンプレート"を参照して、すべてのページに表示されるようにします。 ターミナル・ウィンドウから、次のコマンドを実行します。 gedit app/views/layouts/articles.html.erb
|
10 . |
次のコードを<p style="color: green"><%= flash[:notice] %></p>の直後に追加します。 <div id="unfinished">
|
11 . |
新しいボタンによって使用されるmark_finishedアクションのコードを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。 gedit app/controllers/articles_controller.rb
|
12 . |
ファイルの下部までスクロールします。 最後の'end'の直前に次を追加します。 # POST /articles/mark_finished/1
|
13 . |
ここまでに、データベースを更新してボタンとアクションを追加し、レイアウトにリストを追加しました。 次に、この機能のテストを実行します。 ブラウザに次のURLを入力します。 http://localhost:3000/articles 未完成記事のリストがページ上部に表示されていることを確認します。 「Boning a Duck」リンクを選択します。 「Mark Finished」ボタンをクリックします。 未完成記事のリストからBoning a Duckが削除されたことを確認します。 「Back」を選択します。
|
14 . |
ここまでで、AJAXを試す準備が整いました。 ここでは、ボタンを押すと、画面を再描画することなくウィンドウが自動的に変更されるようにアプリケーションを変更します。 これには、mark_finishedアクションを実行するためのAJAXコマンドを"Mark Finished"ボタンから送信し、次に、"Finished articles"ヘッダーを更新するためのコマンドを返す必要があります。 まず、ボタンをリモート(AJAX)フォームに変更します。 ターミナル・ウィンドウから、次のスクリプトを実行します。 gedit app/views/articles/show.html.erb
|
15 . |
次の文を <%= button_to "Mark Finished", :action => :mark_finished, :id => @article.id %> 以下のとおりに変更します。 <% form_remote_tag :url => { :action => :mark_finished, :id => @article } do %>
|
16 . |
ボタンを押すと、アプリケーションは引き続き更新を実行しますが、ページ全体を送信する代わりに、未完成リストのみを更新するJavaScriptを返す必要があります。リモートのjavascriptテンプレートを使用すると、RailsによってJavaScriptが生成されます。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。 gedit app/views/articles/mark_finished.js.rjs
|
17 . |
次の行を入力します。 page.replace_html("unfinished" , :partial => "unfinished")
|
18 . |
これが機能するためには、すべてのページにデフォルトのJavaScriptサブルーチンが定義されている必要があります。 レイアウトを編集します。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。 gedit app/views/layouts/articles.html.erb
|
19 . |
<%= stylesheet_link_tag 'scaffold' %>の後に、次の行を追加します。 <%= javascript_include_tag :defaults %>
|
20 . |
次に、新しいリモート・テンプレートを使用するように、mark_finishedアクションを更新する必要があります。このテンプレートの名前はアクション名と同じです。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。 gedit app/controllers/articles_controller.rb
|
21 . |
次の部分を # POST /articles/mark_finished/1 以下のとおりに変更します。 # *AJAX* /articles/mark_finished/1
|
22 . |
AJAXリクエスト・フォームを使用して、リストを更新するJavascriptを送り返すようにするための切替えが完了しました。 ブラウザに次のURLを入力します。 http://localhost:3000/articles 新しい記事を作成します。 「New article」を選択します。 TitleにGravityと入力し、Authorに「Julia Child」を選択し、AbstractにGravity makes cakes fallと入力したら、「Create」をクリックします。 Gravityが未完成記事のリストに表示されていることを確認します。 「Gravity」リンクを選択します。 「Mark Finished」をクリックします。 Gravityが即座にリストに表示されなくなります。 ページは再描画されていません。 これは、AJAXの機能によるものです。 このように単純な画面ではWebサーバーが送信しているページが小さいため、違いが分かりにくいかもしれません。 しかし、イメージやフラッシュ、大量データを含む、より複雑な画面でAJAXを使用すると、変更のみがサーバーから送信されるため非常に大きな違いが生じます。 そのような場合は、RailsによるAJAXサポートが大いに役立つでしょう。
|
このチュートリアルで学習した内容は、以下のとおりです。
ここでは、Ruby言語の概要を説明します。 使用するオブジェクトは、以下のとおりです。 Rubyに精通している場合、この項をスキップして次の項に進んでください。
|
Railsで"comics"表に"t.column :price, :float"列を追加するには、以下の手順を実行します。
1 . |
comicモデルを作成できます。 ターミナル・ウィンドウから、次のコマンドを実行します。 ruby script/generate migration add_columns
|
---|---|
2 . |
作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。 gedit db/migrate/008_add_columns.rb
|
3 . |
self.upセクションを次の内容に置き換えて、ファイルを保存して閉じます。 def self.up
|
4 . |
データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。 rake db:migrate 注: 列を削除するには、self.upメソッドに"remove_column :comics, :price"のような行を追加します。列の名前を変更するには、self.upメソッドに"rename_column :comics, :price, :new_price"のような行を追加します。列を変更するには、self.upメソッドに"change_column :comics, :price, :integer"のような行を追加します。
|
![]() |
会社情報 |オラクルとサン | ![]() |