OracleおよびRuby on Railsの使用

<このテキストを削除しないでください。これは、ブラウザ実行時に生成される"主要"なトピック一覧のプレースホルダです。>

目的

このチュートリアルでは、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スクリプトの作成タスクでは、最初にデータベースの接続を作成します。 以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してconnect.rbを実行します。


export NLS_LANG=American_America.UTF8
ruby connect.rb

接続に成功すると、上記のメッセージが表示されます。接続に失敗すると、エラーが表示されます。

connect.rbファイルの内容は、次のとおりです。

# connect.rb: Create connections to Oracle
require 'config.rb'
begin
# login as normal user
conn1 = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
puts "login as normal user succeeded."
conn1.logoff
puts "logoff succeeded."
puts
# login as DBA
conn2 = OCI8.new('sys', 'oracle', DB_SERVER, :SYSDBA)
puts "login with DBA privilege succeeded."
conn2.logoff
puts "logoff succeeded."
rescue OCIError
# display the error message
puts "OCIError occured!"
puts "Code: " + $!.code.to_s
puts "Desc: " + $!.message
end
puts '-'*80

 

.

このチュートリアルの残りのスクリプトに含まれるコマンドは、以下のとおりです。

require 'config.rb'

#create connection
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)

# operations on conn goes here
#log out
conn.logoff

 

データの問合せ

この項で使用するコマンドは、以下のとおりです。

OCI8#parse (sql)

カーソルを作成し、SQL文の実行を準備して、OCI8::Cursorインスタンスを返します。

OCI8#exec (sql, *bindvars)

SQL文を実行します。 戻り値のタイプは、SQL文のタイプによって異なります。 bindvarsを指定すると、実行前にバインド変数としてバインドされます。

OCI8::Cursor#exec(*bindvars) カーソルに割り当てられたSQL文を実行します。 戻り値のタイプは、SQL文のタイプによって異なります。
OCI8::Cursor#getColNames 選択リストの名前を配列で取得します。 exec後にこのメソッドを使用してください。

簡単な問合せを作成して結果を表示するには、以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してfetch.rbスクリプトを実行します。

ruby fetch.rb

出力のスクリーンショットは、以下のとおりです。

fetch.rbファイルの内容は、次のとおりです。

#fetch.rb: Fetch data from database
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
# parse and exec the statement
cursor = conn.parse("select * from regions")
cursor.exec
# output column names
puts cursor.getColNames.join(",")
# output rows
while r = cursor.fetch
puts r.join(",")
end
# close the cursor and logoff
cursor.close
conn.logoff
puts '-'*80

 

.

Rubyに固有のコードを記述する別の方法があります。 ターミナル・ウィンドウから、次のコマンドを実行してfetch_r.rbスクリプトを実行します。

ruby fetch_r.rb
出力のスクリーンショットは、以下のとおりです。

fetch_r.rbファイルの内容は、次のとおりです。

# fetch_r.rb: Fetch in a more ruby-like way
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
# Fetch and display the rows in a block
nrow = conn.exec("select * from regions") do |r|
puts r.join(",")
end
# Display count of rows
puts ' '*30 + nrow.to_s + " rows were fetched."
conn.logoff
puts '-'*80

 

.

フェッチされる行数が多い場合、プリフェッチを使用するとパフォーマンスが向上します。 ターミナル・ウィンドウから、次のコマンドを実行してprefetch.rbスクリプトを実行します。

ruby prefetch.rb
出力のスクリーンショットは、以下のとおりです。

prefetch.rbファイルの内容は、次のとおりです。

# prefetch.rb: Prefetch data
require 'config.rb'
SELECT_STATEMENT = "select a.first_name, a.last_name, b.first_name, b.last_name, a.salary - b.salary salarydiff from employees a, employees b where b.id > a.id"
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
# Execute statement with different prefetch sizes
[nil,100].each do |prefetchrows|
cursor = conn.parse(SELECT_STATEMENT)
if prefetchrows
cursor.prefetch_rows = prefetchrows
else
prefetchrows = "default"
end
puts "Executing with prefetch rows = #{prefetchrows}"
time1 = Time.now
cursor.exec
while r = cursor.fetch()
# puts r.join(",")
end
# Display count of rows
puts ' '*30 + cursor.row_count.to_s + " rows were fetched."
time2 = Time.now
puts "Time cost: " + (time2-time1).to_s
puts
end
conn.logoff
puts '-'*80

 

変数のバインド

バインド変数を使用すると、コードの再利用性が向上し、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] バインド変数の値を取得/設定します。

この例でバインド変数を使用するには、以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してbind.rbスクリプトを実行します。

ruby bind.rb

出力のスクリーンショットは、以下のとおりです。

bind.rbファイルの内容は、次のとおりです。

# bind.rb: How to bind variables
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
# Prepare the data, also display what's hard-coded statement
conn.exec("DELETE FROM test_bind")
conn.exec("INSERT INTO test_bind VALUES(1, 'Unknown')")
conn.exec("INSERT INTO test_bind VALUES(2, 'Unknown')")
conn.exec("INSERT INTO test_bind VALUES(3, 'Unknown')")
# Now update the data using bind variables.
cursor = conn.parse("UPDATE test_bind SET name = :name WHERE id = :id")
cursor.bind_param(1,nil,String,100) # Or: cursor.bind_param(1, ' '*100)
cursor.bind_param(2,Fixnum) # Or: cursor.bind_param(2, id)
id = 1
['China', 'Korea', 'Japan'].each { |country|
cursor[1] = country
cursor[2] = id
cursor.exec
id = id + 1
}
# Fetch back the updated data
conn.exec("SELECT * FROM test_bind").fetch do |row|
puts row.join(',')
end
conn.logoff
puts '-'*80

 

.

バインド変数を使用してパフォーマンスの向上をテストするには、次のコマンドを実行してbind_perf_test.rbスクリプトを実行します。

ruby bind_perf_test.rb
出力のスクリーンショットは、以下のとおりです。

bind_perf_test.rbファイルの内容は、次のとおりです。

# bind_perf_test.rb: Performance test for binding variables
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
# Not using bind varables.
puts "Fetching result, not using bind variables:"
time1 = Time.now
(100..200).each { |id|
cursor = conn.parse("SELECT first_name FROM employees WHERE id = #{id}")
cursor.exec
#puts id.to_s + " --> " + cursor.fetch[0]
}
time2 = Time.now
puts "Time cost: " + (time2-time1).to_s
puts
# Using bind varables.
puts "Fetching result, using bind variables:"
time1 = Time.now
cursor = conn.parse("SELECT first_name FROM employees WHERE id = :id")
cursor.bind_param(1, Fixnum)
(100..200).each { |id|
cursor[1] = id
cursor.exec
#puts id.to_s + " --> " + cursor.fetch[0]
}
time2 = Time.now
puts "Time cost: " + (time2-time1).to_s
# End of the test
conn.logoff
puts '-'*80

 

データ型の定義

この項で使用するコマンドは、以下のとおりです。

OCI8::Cursor#define(pos, type, length = nil)

parseおよびexec内でこのメソッドを使用します。 posは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() トランザクションをロールバックします。

トランザクションの管理方法を学習するには、以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してtransaction.rbスクリプトを実行します。

ruby transaction.rb

このスクリプトは、conn1接続を使用して行を更新します。 Oracleの新しいデータは、コミットされるまで元のデータベース・セッションにのみ表示されます。 出力のスクリーンショットは、以下のとおりです。

この場合、conn2接続は、conn1のコミットされていないトランザクションで発生した内容を認識していません。

transaction.rbファイルの内容は、次のとおりです。

# transaction.rb: How to use transactions
require 'config.rb'
# Create connections to Oracle
conn1 = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
conn2 = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
conn1.exec("DELETE FROM test_transaction")
conn1.exec("INSERT INTO test_transaction VALUES(1, 'old value')")
conn1.commit
#conn1.autocommit = true
puts "OCI8.autocommit = " + conn1.autocommit.to_s
puts "conn1 updated the name to 'something new'";
conn1.exec("UPDATE test_transaction SET name = 'something new' WHERE id = 1");
#conn1.commit
puts "conn2 got the name as '" +
conn2.exec('SELECT name FROM test_transaction WHERE id = 1').fetch[0] + "'"
conn1.logoff
conn2.logoff
puts '-'*80

 

.

transaction.rbスクリプトを更新し、conn1.autocommit = trueをコメントアウトして、ファイルを保存します。

次のコマンドを使用して、スクリプトを再実行します。

ruby transaction.rb

conn2が新しい内容を認識します。 出力のスクリーンショットは、以下のとおりです。

 

.

各行を個別にコミットすると、サーバーに余分なロードが発生します。 各行で個別にコミットする場合とトランザクションの最後にコミットする場合のパフォーマンスの違いを比較できます。 違いをテストするには、次のコマンドを使用してtrans_perf_test.rbスクリプトを実行します。

ruby trans_perf_test.rb

2つ目の数値が1つ目の数値より小さいことを確認します。 出力のスクリーンショットは、以下のとおりです。

trans_perf_test.rbファイルの内容は、次のとおりです。

# trans_perf_test.rb: Performance test for transactions
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
conn.exec("DELETE FROM test_transaction")
conn.commit
# Commit on each time
conn.autocommit = true
time1 = Time.now
300.times{
conn.exec("INSERT INTO test_transaction VALUES(1, 'something')")
}
time2 = Time.now
# Commit on the last step
conn.autocommit = false # It's the default
time3 = Time.now
300.times{
conn.exec("INSERT INTO test_transaction VALUES(1, 'something')")
}
conn.commit
time4 = Time.now
# Output the comparation
puts "Time cost of each-time commit(sec): " + (time2-time1).to_s
puts "Time cost of one-time commit(sec) : " + (time4-time3).to_s
conn.logoff
puts '-'*80

 

PL/SQLの使用

PL/SQLは、SQLを拡張したOracleの手続き型言語です。 PL/SQLストアド・プロシージャおよびストアド・ファンクションがデータベースに格納されるため、迅速なアクセスが実現します。 PL/SQLストアド・プロシージャを使用すると、アプリケーションのデータベースへのアクセス方法に関係なく、すべてのデータベース・アプリケーションでロジックを再利用できます。 データをプログラム(Rubyなど)に抽出して処理するよりも速く、多くのデータ関連操作をPL/SQLで実行できます。

この項で使用するコマンドは、以下のとおりです。

DBMS_UTILITYおよびDBMS_OUTPUT

Oracleストアド・パッケージ。 TO_CHARは、組込み関数です。

RubyスクリプトでPL/SQLプロシージャおよびファンクションを呼び出すには、以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してplsql.rbスクリプトを実行します。

ruby plsql.rb

出力のスクリーンショットは、以下のとおりです。

plsql.rbファイルの内容は、次のとおりです。

# plsql.rb: Call PL/SQL procedures and functions
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
puts 'Get version information from Oracle:'
cursor = conn.parse("BEGIN DBMS_UTILITY.db_version(:ver, :comp); END;")
cursor.exec(' '*50,' '*50)
puts "Oracle DB Version: " + cursor[1]
puts "Oracle DB Compatibility: " + cursor[2]
puts
puts 'Call TO_CHAR function:'
cursor = conn.parse("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;")
cursor.exec('ABCD', 123)
puts "TO_CHAR input: " + cursor[2].to_s
puts "TO_CHAR output: " + cursor[1]
puts
puts 'Get DBMS_OUTPUT:'
conn.exec("BEGIN DBMS_OUTPUT.ENABLE(NULL); END;")
conn.exec("BEGIN DBMS_OUTPUT.put_line('Hello world!'); END;")
conn.exec("BEGIN DBMS_OUTPUT.put_line('Can you see me?'); END;")
cursor = conn.parse("BEGIN DBMS_OUTPUT.get_line(:line, :status); END;")
cursor.bind_param(':line', nil, String, 255)
cursor.bind_param(':status',Fixnum)
while true
cursor.exec
break if cursor[':status'] == 1
puts cursor[':line']
end
puts '-'*80

 

LOBの使用:イメージの格納/取得

Oracleキャラクタ・ラージ・オブジェクト(CLOB)およびバイナリ・ラージ・オブジェクト(BLOB)列(およびPL/SQL変数)には、大量(ギガバイト)の文字とバイナリ・データを格納できます。 この項で使用するコマンドは、以下のとおりです。

OCI8::BLOB#available

BLOBを使用できるかどうか確認します。 BLOBを使用するには、最初にEMPTY_BLOB()を挿入する必要があります。

OCI8::BLOB#read(size = nil) BLOBから最大サイズのバイトで読み取ります。サイズが省略される場合はファイルの最後まで読み取ります。
OCI8::BLOB#write(string) 特定の文字列をBLOBに書き込みます。

小さいアプリケーションを作成してデータベースにイメージをロードして表示するには、以下の手順を実行します。

.

PNGファイルは、スクリプト・ファイルと同じフォルダにあります。 downloadというフォルダを作成します。 ターミナル・ウィンドウから、次のコマンドを実行してblob.rbスクリプトを実行します。

mkdir download
ruby blob.rb

出力のスクリーンショットは、以下のとおりです。

blob.rbファイルの内容は、次のとおりです。

#blob.rb: Save and Load BLOB
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
conn.exec("DELETE FROM test_blob")
# Must insert a EMPTY_BLOB before save real data
cursor = conn.parse("INSERT INTO test_blob VALUES(:name, EMPTY_BLOB())")
Dir["*.png"].each do |fname|
cursor.exec(fname)
end
# Save BLOB into Oracle
conn.exec("SELECT name,image FROM test_blob") do |name, image|
puts "uploading file: " + name
File.open(name, 'r') do |f|
image.write(f.read)
image.size = f.pos
end
end
# Load BLOB from Oracle
conn.exec("SELECT name,image FROM test_blob") do |name, image|
puts "downloading file: " + name
File.open("download/"+name, 'w') do |f|
f.write(image.read)
end
end
# End
conn.logoff
puts '-'*80

 

.

ruby.pngファイルに対する権限を確認します。 次のコマンドを実行します。

ls -l ruby.png download/ruby.png

 

XMLの使用

Oracleデータベースのすべてのエディションには、"XML DB"が含まれます。 このテストでは、OracleからRubyにXMLデータを返す基本事項を説明します。 この項で使用するコマンドは、以下のとおりです。

DBMS_XMLGEN.getxml (statement)

SELECT文に基づいて、リレーショナル・データからXMLを作成します。 CLOBが返されます。

Oracleの基本的なXML機能を学習するには、以下の手順を実行します。

.

ターミナル・ウィンドウから、次のコマンドを実行してxml.rbスクリプトを実行します。

ruby xml.rb

出力のスクリーンショットは、以下のとおりです。

xml.rbファイルの内容は、次のとおりです。

# xml.rb: Generate a xml document based on relational data
require 'config.rb'
# Create a connection to Oracle
conn = OCI8.new(DB_USER, DB_PASSWORD, DB_SERVER)
sql = "SELECT DBMS_XMLGEN.getxml('
SELECT dept.name,dept.id,
CURSOR(
SELECT emp.first_name,emp.last_name,emp.phone_number
FROM employees emp
WHERE emp.department_id=dept.id
) AS employees
FROM departments dept
WHERE dept.id in (20,110)'
) AS xml
FROM dual"
# Fetch as CLOB
puts conn.exec(sql).fetch[0].read
conn.logoff
puts '-'*80

 

ActiveRecordの使用

ActiveRecordは、ビジネス・オブジェクトとデータベース表に接続して、単一のラッピングでロジックとデータを表す永続的なドメイン・モデルを作成します。 これは、オブジェクト・リレーショナル・マッピング(ORM)設計パターンの実装です。 この例でActiveRecordを使用するには、以下の手順に従います。

.

ターミナル・ウィンドウから、次のコマンドを実行してactiverecord.rbスクリプトを実行します。

ruby activerecord.rb

出力のスクリーンショットは、以下のとおりです。

activerecord.rbファイルの内容は、次のとおりです。

# activerecord.rb: Using ActiveRecord, the ORM module
require 'config.rb'
require 'rubygems'
require 'active_record'
# Establish a connection to Oracle
ActiveRecord::Base.establish_connection(
:adapter => "oracle_enhanced",
:database => DB_SERVER,
:username => DB_USER,
:password => DB_PASSWORD )
# Define the Classes, they are mapped to table countries and regions
class Country < ActiveRecord::Base
belongs_to :region
end
class Region < ActiveRecord::Base
has_many :countries
end
# Enjoy the automatic Object-Relation Mapping
cty = Country.find('CN')
puts 'CN refers to [' + cty.name + ']'
puts '[' + cty.name + '] is in [' + cty.region.name + ']'
puts
rgn = Region.find(cty.region.id)
puts 'Countries in the same region with [' + cty.name + ']'
rgn.countries.each { |country| puts ' - ' + country.name }
puts '-'*80

 

移行と足場を使用した、Ruby on Railsアプリケーションの構築

このチュートリアルの後半では、以下の用語を使用します。

Rake
モデル アプリケーション内の重要オブジェクトを表すRubyクラスであり、ActiveRecordのORMを介してデータベース表に関連付けられています。
移行 開発者は、データ記述言語(DDL)の代わりにRubyでデータベース・オブジェクトを作成、変更、および削除できます。
足場 ActiveRecordクラスによって反映されるエントリを作成、編集、参照、削除できるデータの簡単なインタフェースを提供します。 足場が作成されると、そこにはコントローラ・ファイル(アプリケーション・ユーザーが次に移動するページを決定する)とビュー・ファイル(アプリケーション・ユーザーが参照するページをレンダリングする)が含まれます。

移行と足場を使用してRailsアプリケーションを作成するには、以下の手順を実行します。

.

holappというもっとも基本的なRailsアプリケーションを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

rails holapp
cd holapp
gedit config/database.yml

 

.

config/database.ymlファイルのdevelopmentセクションを次の内容に置き換えて、ファイルを保存して閉じます。

development:
    adapter: oracle_enhanced
    username: rubyhol
    password: welcome
    database: localhost/orcl

 

.

comicモデルを作成できます。 ターミナル・ウィンドウから、次のコマンドを実行します。

ruby script/generate model comic

 

.

作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit db/migrate/*_create_comics.rb

 

.

self.upセクションを次の内容に置き換えて、ファイルを保存して閉じます。

  def self.up
    create_table :comics do |t|
          t.column :name,:string
   t.column :description, :string
   t.column :price, :float
    end
  end

 

.

データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。

rake db:migrate

 

.

次のコマンドを使用して、comicモデルの足場を作成できます。

ruby script/generate scaffold --skip-migration comic name:string description:string price:float

 

.

Webrickは、サーブレットを使用して機能を拡張するRubyで記述されたHTTPサーバー・ライブラリです。 次のコマンドを使用して、Webrickサーバーを起動できます。

ruby script/server

 

.

アプリケーションを表示できます。 ブラウザ・ウィンドウを開いて、次のURLを入力します。 アプリケーションが正しく動作することを確認するために「New comic」をクリックして、レコードを作成します。

http://localhost:3000/comics

コミック情報を入力し、「Create」をクリックします。

コミックが正しく作成されました。 「Back」をクリックします。

 

.

コミックをもう1つ作成します。 「New comic」を選択します。

コミック情報を入力し、「Create」をクリックします。

もう1つのコミックが正しく作成されました。 「Back」をクリックします。

 

.

両方のコミックが表示されています。 ここで、編集を実行することもできます。最初のコミックに対して「Edit」をクリックします。

何らかの情報を変更し、「Update」をクリックします。

コミックが更新されました。 「Back」をクリックします。

 

.

コミックを破棄することもできます。 いずれかのコミックに対して、「Destroy」を選択します。

OK」をクリックして確認します。

コミックが更新されました。 「Back」をクリックします。

 

.

スクリプト・サーバーを停止します。 サーバーが実行されているウィンドウで、[Ctrl]を押しながら[C]を押します。

 

データ関係のモデル化とRuby on Railsを使用したアプリケーションの構築

この項では、さまざまなデータ関係をモデル化し、これらのモデルに対してRailsでアプリケーションを構築する方法について説明します。 ここでは、記事および著者のデータベースを維持するアプリケーションを作成することで、その方法を学習します。

著者と記事の作成

まず、著者と記事を入力できるアプリケーションを作成します。 その他に、フォームを変更して、記事の入力時に著者リストをポップアップ表示し、ListingページとShowページで記事の著者を表示します。 ここでは、このアプリケーションに対して、表と表の間に1対1関係を定義します。 以下の手順を実行します。

.

別のターミナル・ウィンドウを開いて、次のコマンドを実行します。

cd /home/rubyhol/holapp
source /etc/bashrc

 

.

著者用モデルを含む足場を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

ruby script/generate scaffold author name:string vocation:string

 

.

記事用モデルを含む足場を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

ruby script/generate scaffold article title:string author_id:integer abstract:text

 

.

次に、記事モデルと著者モデルの関係をRailsに伝える必要があります。 そのため、生成済みのモデル・スクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/models/author.rb

 

.

ファイルの内容を以下に置き換えて、ファイルを保存して閉じます。

class Author < ActiveRecord::Base
   has_one :article
end

 

.

作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/models/article.rb

 

.

ファイルの内容を以下に置き換えて、ファイルを保存して閉じます。

class Article < ActiveRecord::Base
   belongs_to :author
end

 

.

データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。

rake db:migrate

 

.

ターミナル・ウィンドウから、次のコマンドを実行してスクリプト・サーバーを再起動します。

script/server &

 

.

アプリケーションを表示できます。 ブラウザ・ウィンドウを開いて次のURLを入力し、「New author」を選択します。

http://localhost:3000/authors

新しい著者を入力し、「Create」をクリックします。

著者が正しく作成されました。 「Back」をクリックします。

 

.

著者をもう1人作成します。 「New author」を選択します。

もう1人の著者を入力し、「Create」をクリックします。

著者が正しく作成されました。 「Back」をクリックします。

追加した著者のリストが表示されます。

 

.

次に、記事をいくつか作成します。 次のURLを入力して、「New article」を選択します。

http://localhost:3000/articles

タイトルと要約を入力し、著者としてJulia Childを指定します。 次に、「Create」をクリックします。

記事が正しく作成されました。

Author: 0と表示されていることに注意してください。 これは、author_idに無効な値が設定されているために、"Julia Child"が0に変更されているためです。 次の項では、新規フォームと編集フォームを修正して、名前を表示したポップアップ・リストから著者を選択すると、コードにauthor_idが返されるようにします。

 

記事用フォームおよびリストの修正

ここでは、生成されたフォームを修正して、記事を作成する際に著者フィールドがポップアップ表示されるようにします。 また、ListingページとShowページを修正して、著者が正しく表示されるようにします。 以下の手順を実行します。

.

新しいターミナル・ウィンドウで、次のコマンドを入力します(先ほどのウィンドウではスクリプト・サーバーが実行されているため)。

cd holapp
gedit app/views/articles/new.html.erb

次の行を

<%= f.text_field :author_id %>

以下のとおりに変更します。

<%= f.collection_select(:author_id, Author.all, :id, :name) %>

ファイルは、以下のようになります。

 

.

articlesディレクトリのedit.html.erbファイルに対しても、同じ変更を行います。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/edit.html.erb

 

.

次の行を

<%= f.text_field :author_id %>

以下のとおりに変更します。

<%= f.collection_select(:author_id, Author.all, :id, :name) %>

ファイルは、以下のようになります。

 

.

再度、次のURLを入力します。 先ほど作成した記事がリストに表示されていることを確認します。 「Edit」を選択します。

http://localhost:3000/articles

選択リストから著者を選択できるようになっています。 「Julia Child」を選択します。 次に、「Update」をクリックします。

記事が正しく更新されました。

Author: 1と表示されていることに注意してください。 これは、author_idの値です。 この値を名前に変更できます。

 

.

articlesディレクトリにあるindex.html.erbファイルを変更します。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/index.html.erb

 

.

次の行を

<td><%=h article.author_id %></td>

以下のとおりに変更します。

<td><%=h article.author.name %></td>

ファイルは、以下のようになります。

 

.

articlesディレクトリのedit.html.erbファイルに対しても、同じ変更を行います。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/show.html.erb

 

.

次の行を

<%=h article.author_id %>

以下のとおりに変更します。

<%=h article.author.name %>

ファイルは、以下のようになります。

 

.

再度、次のURLを入力します。 リストに著者が表示されていることを確認します。 「Show」を選択します。

http://localhost:3000/articles

Showモードですべての情報を確認できるようになりました。

 

1人の著者による複数記事の作成

ここでは、1人の著者が複数記事を作成できるようにします。 これにより、Authors表とArticles表の関係が1対多関係に変わります。 以下の手順を実行します。

.

この関係を表示するには、author.rbファイルを変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/models/author.rb

 

.

次の行を

 has_one : article 

以下のとおりに変更します。

 has_many : articles 

 

.

再度次のURLを入力して、「New article」を選択します。

http://localhost:3000/articles

新しい記事を作成します。 著者として「Julia Child」を選択し、「Create」をクリックします。

記事が正しく作成されました。 「Back」をクリックします。

両方の記事が表示されています。

 

複数の著者による記事の共著

複数の著者が共同で1つの記事を作成できるようにします。 これにより、Authors表とArticles表の関係が多対多関係に変わります。 以下の手順を実行します。

.

再度、authors.rbファイル内の関係を変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/models/author.rb

 

.

次の行を

 has_many :articles 

以下のとおりに変更します。

 has_and_belongs_to_many :articles 

 

.

article.rbファイルも変更する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/models/article.rb

 

.

次の行を

 belongs_to :author 

以下のとおりに変更します。

 has_and_belongs_to_many :authors 

 

.

AuthorsとArticlesの間に結合表を作成する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。

script/generate migration CreateArticlesAuthors

 

.

次に、先ほど作成したファイルを更新して、著者と記事を格納するための表を作成する必要があります。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit db/migrate/*_create_articles_authors.rb

 

.

次の行を

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

 

.

データベースの移行にRakeを実行して、ターゲット表を作成できます。 ターミナル・ウィンドウで次のコマンドを入力します。

rake db:migrate

 

.

再度、次のURLを入力します。 エラーが発生したことを確認します。

http://localhost:3000/articles

 

.

多対多関係が作成されたことで、Articleモデルに定義されたメソッド名は、authorauthor_idからauthorsauthor_idsに変更されました。 エラーを修正するには、new.html.erbファイルで、先ほど作成したポップアップ・リストと表示フィールドを作成および編集して、複数の著者に対応できるようにする必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。


gedit app/views/articles/new.html.erb

 

.

次の行を

<%= f.collection_select(:author_id, Author.all, :id, :name) %>

以下のとおりに変更します。

<%= f.collection_select(:author_ids, Author.all, :id, :name, {},
                        {:multiple => :multiple} ) %>

ファイルは、以下のようになります。

 

.

また、articlesディレクトリにあるedit.html.erbファイルを変更する必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/edit.html.erb

 

.

次の行を

<%= f.collection_select(:author_id, Author.all, :id, :name) %>

以下のとおりに変更します。

<%= f.collection_select(:author_ids, Author.all, :id, :name, {},
                        {:multiple => :multiple} ) %>

ファイルは、以下のようになります。

 

.

また、articlesディレクトリにあるindex.html.erbファイルを変更する必要があります。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/index.html.erb

 

.

次の行を

<th>Author</th>

以下のとおりに変更します。

<th>Authors</th>

すべての著者名を取得して、結合(連結)する必要があります。 次の行を

<td><%=h article.author.name %></td>

以下のとおりに変更します。

<td><%=h article.authors.map {|auth| auth.name}.join(", ") %></td>

ファイルは、以下のようになります。

 

.

最後に、articlesディレクトリにあるshow.html.erbファイルを変更します。 ターミナル・ウィンドウに次のコマンドを入力します。

gedit app/views/articles/show.html.erb

 

.

次の行を

<b>Author: </b>
<%=h article.author.name %>

以下のとおりに変更します。

<b>Authors: </b>
<%=h article.authors.map {|auth| auth.name}.join(", ") %>

ファイルは、以下のようになります。

 

.

再度、次の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とRuby on Railsの使用

AJAXの概念は、ほとんど"通常の"アプリケーション並みの高機能なブラウザを持つことにあります。 インタラクティブなページを作成して、ウィンドウを再描画することなく、サーバーから更新データを取得することができます。

たとえば、最初は作成中であったものが後で完成記事となる場合もあるでしょう。 ここでは、未完成記事のリストを常に表示する必要があるとします。 1つの記事に完成のマークを付けたら、ページ全体を再描画しなくてもリストが更新されるようにする必要があります。


AJAXを使用する前に、非AJAXの"未完成"リストから開始するともっとも簡単です。 記事が完成しているかどうかを把握できるように、データベース表を更新する必要があります。 記事は未完成の状態から始まり、完成マークを付けるためのボタンが表示されます。 容易にアクセスできるようにするため、レイアウト内に未完成記事のリストを作成します。 以下の手順を実行します。

.

is_finishedというブール列を作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

script/generate migration AddIsFinishedToArticle is_finished:boolean

 

.

次に、既存記事に未完成マークを付けます。 ターミナル・ウィンドウから、次のコマンドを実行します。

gedit db/migrate/*_add_is_finished_to_article.rb

 

.

次の行を

  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

 

.

データベースを更新します。 ターミナル・ウィンドウで次のコマンドを入力します。

rake db:migrate

 

.

新しいmark_finishedアクションを呼び出す"Mark Finished"ボタンを追加します。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit app/views/articles/show.html.erb

 

.

<%= link_to 'Back', articles_path %>の後に、次の行を追加します。

<%= button_to "Mark Finished", :action => :mark_finished, :id  => @article.id %>

 

.

レイアウトを更新して、未完成記事へのリンクを表示します。 このコードは、メインのレイアウトから分離しておく必要があります。 新しい"部分テンプレート"(フル・テンプレートではないことを示す"_"(アンダースコア)文字が先頭に付きます)を作成します。 このテンプレートはis_finishedがfalseである記事を検索し、これらに対するリンクを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

gedit app/views/articles/_unfinished.html.erb

 

.

ファイルに次のコードを追加します。

  <div class="unfinished-title">Unfinished Articles</div>
<table>
  <% for article in Article.all(:conditions => {:is_finished => false}) %>
   <tr> <%= link_to article.title, :action => :show, :id => article.id %> </tr>
  <% end %>
</table>

 

.

次に、既存のレイアウトから新しい"部分テンプレート"を参照して、すべてのページに表示されるようにします。 ターミナル・ウィンドウから、次のコマンドを実行します。

gedit app/views/layouts/articles.html.erb

 

.

次のコードを<p style="color: green"><%= flash[:notice] %></p>の直後に追加します。

 <div id="unfinished">
 <%= render(:partial => "unfinished") %>
</div>

 

.

新しいボタンによって使用されるmark_finishedアクションのコードを作成します。 ターミナル・ウィンドウから、次のコマンドを実行します。

gedit app/controllers/articles_controller.rb

 

.

ファイルの下部までスクロールします。 最後の'end'の直前に次を追加します。

    # POST /articles/mark_finished/1
  # POST /articles/mark_finished/1.xml
  def mark_finished
    @article = Article.find(params[:id])
    @article.update_attribute(:is_finished, true)

    respond_to do |format|
      format.html { redirect_to(:action => :show) }
      format.xml  { head :ok }
    end
  end

 

.

ここまでに、データベースを更新してボタンとアクションを追加し、レイアウトにリストを追加しました。 次に、この機能のテストを実行します。 ブラウザに次のURLを入力します。

    http://localhost:3000/articles

未完成記事のリストがページ上部に表示されていることを確認します。 「Boning a Duck」リンクを選択します。

Mark Finished」ボタンをクリックします。

未完成記事のリストからBoning a Duckが削除されたことを確認します。 「Back」を選択します。

 

.

ここまでで、AJAXを試す準備が整いました。 ここでは、ボタンを押すと、画面を再描画することなくウィンドウが自動的に変更されるようにアプリケーションを変更します。 これには、mark_finishedアクションを実行するためのAJAXコマンドを"Mark Finished"ボタンから送信し、次に、"Finished articles"ヘッダーを更新するためのコマンドを返す必要があります。 まず、ボタンをリモート(AJAX)フォームに変更します。 ターミナル・ウィンドウから、次のスクリプトを実行します。

  gedit app/views/articles/show.html.erb

 

.

次の文を

  <%= button_to "Mark Finished", :action => :mark_finished, :id  => @article.id %>

以下のとおりに変更します。

  <% form_remote_tag :url => { :action => :mark_finished, :id  => @article } do %>
 <%= submit_tag "Mark Finished" %>
<% end %>

 

.

ボタンを押すと、アプリケーションは引き続き更新を実行しますが、ページ全体を送信する代わりに、未完成リストのみを更新するJavaScriptを返す必要があります。リモートのjavascriptテンプレートを使用すると、RailsによってJavaScriptが生成されます。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。

  gedit app/views/articles/mark_finished.js.rjs

 

.

次の行を入力します。

  page.replace_html("unfinished" , :partial => "unfinished")

 

.

これが機能するためには、すべてのページにデフォルトのJavaScriptサブルーチンが定義されている必要があります。 レイアウトを編集します。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。

gedit app/views/layouts/articles.html.erb

 

.

<%= stylesheet_link_tag 'scaffold' %>の後に、次の行を追加します。

<%= javascript_include_tag :defaults %>

 

.

次に、新しいリモート・テンプレートを使用するように、mark_finishedアクションを更新する必要があります。このテンプレートの名前はアクション名と同じです。 ターミナル・ウィンドウから、次のコマンドを実行して新規ファイルを作成します。

gedit app/controllers/articles_controller.rb

 

.

次の部分を

    # POST /articles/mark_finished/1
  # POST /articles/mark_finished/1.xml
  def mark_finished
    @article = Article.find(params[:id])
    @article.update_attribute(:is_finished, true)

    respond_to do |format|
      format.html { redirect_to(:action => :show) }
      format.xml  { head :ok }
    end
  end

以下のとおりに変更します。

    # *AJAX* /articles/mark_finished/1
  def mark_finished
    @article = Article.find(params[:id])
    @article.update_attribute(:is_finished, true)

    respond_to do |format|
      format.js
    end
  end

 

.

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言語の概要を説明します。 使用するオブジェクトは、以下のとおりです。 Rubyに精通している場合、この項をスキップして次の項に進んでください。


変数

$var #グローバル変数
@var  #インスタンス変数
VAR  #定数
SomeClass::VAR #クラス内の定数
varまたは_var  #ローカル変数


擬似変数

self、nil、true、false

FILE #現在のソース・ファイル
LINE #現在の行

配列

[1,2,3]

["dog", "cat", "pig"]は%w(dog cat pig)と同じ

[ 1, 'cat', 3.14 ]  

ハッシュ

{expr1 => exprA, expr2 => exprB }

hashvar = { 'dog' => 'Frank', 'cat' => 'Sissi', 'donkey' => 'Tim' }
hashvar.length # 3
hashvar['dog']   # "Frank"
hashvar['cow'] = 'Ethan'

範囲

expr1 .. expr2 #最後の要素を含む
expr1 ... expr2 #最後の要素を除く

文字列リテラル

#二重引用符で囲まれた文字列には式展開が適用されます
"remember to escape \" and \\ #{expression_substituted}"
#一重引用符で囲まれた文字列は評価されません
'remember to escape \' and \\ #{expression_not_substituted}'


イテレータ

 

[ 1, 1, 2, 3, 5 ].each {|val| print val, " " } # 1 1 2 3 5

  3.times do print "Ho! " end # Ho! Ho! Ho!

メソッドの呼出し

method(args1, arg2)

method(*array)、method(array_member1, array_member2, …)と同じ

演算子

+, -, *, /, %, **, &, |, ^, <<, >>, &&, ||
foo += 5
foo, bar, baz = 1, 2, 3
foo, bar = 1          # foo = 1; bar = nil
foo,*bar = 1, 2, 3          #foo = 1; bar = [2, 3]と同じ(複数の割当てを表す*を使用して配列を割り当てます)


開始ブロック

# beginは大文字のBEGINとは異なります(まったく違う意味になります)
# expr1に例外が発生すると、rescueはexpr2を実行します
# kind_of?. else句によって実行されるerror_typeの照合は、rescueの後にexpr1で例外が発生しない場合に
# 実行されます
# ensure句は、伝播プロセス中に捕捉されない例外が存在する場合でもブロックの終了時に必ず実行されます

begin
  expr1.. [rescue [error_type,..]
  expr2..]..
[else
  expr3..]
[ensure
  expr4..]
end


ブロック

search_engines =
  %w[Google Yahoo MSN].map do |engine|
    "http://www." + engine.downcase + ".com"
  end


制御構造

falseとnilはfalseであり、その他はすべてtrueです

if expr [then]
  expr...
[elsif expr [then]
  expr...]...
[else
  expr...]
end

unless expr [then]
  expr...
[else
  expr...]
end

expr1 if expr2          # expr2がtrueの場合、expr1を実行します
expr1 unless expr2   # expr2がfalseの場合、expr1を実行します

# ===演算子を使用して、case文を比較します
case expr
[when expr [, expr]...[then]
  expr..]..
[else
  expr..]
end

while expr [do]
  #コードをここに記述
end

until expr [do]
  #コードをここに記述
end

expr1 while expr2              # expr2がtrueの間、expr1を評価し続けます
expr1 until expr2              # expr2がfalseの間、expr1を評価し続けます
begin expr1 until expr2     #expr2がtrueになるまでの間に、少なくとも1回expr1を評価します

for lhs... in expr [do]
  expr..
end

#ループ本文に使用できる2つの特別なキーワードがあります
next      #もっとも内側のループの次の反復へジャンプします

redo    #ループ条件を確認しないでもっとも内側のループ
           #の現在の反復を再開します

付録:Railsの移行を使用したデータベース表の変更方法

Railsで"comics"表に"t.column :price, :float"列を追加するには、以下の手順を実行します。

.

comicモデルを作成できます。 ターミナル・ウィンドウから、次のコマンドを実行します。

ruby script/generate migration add_columns

 

.

作成されたスクリプトを編集します。 ターミナル・ウィンドウで次のコマンドを入力します。

gedit db/migrate/008_add_columns.rb

 

.

self.upセクションを次の内容に置き換えて、ファイルを保存して閉じます。

  def self.up
add_column :comics, :author, :string
  end

 

.

データベースの移行に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"のような行を追加します。
また、"rake db:migrate VERSION=xx"(xxはロールバックするバージョン)コマンドを発行して、移行操作をロールバックできます。

 

Hardware and Software Engineered to Work Together 会社情報 |オラクルとサン | Oracle RSS Feeds | 採用情報 | お問い合わせ | サイトマップ | 情報保護基本方針 | ウェブサイトのご使用条件 | 個人情報保護基本方針