データベースとモデル
データベース |
モデルオブジェクト |
レコード(行) |
ひとつのデータ |
フィールド(列) |
データの属性 |
テーブル |
レコード×フィールドの集合 |
-
- ORM(Object-Relational Mapping)
データベースのレコードとオブジェクトを紐付けて直感的に扱う仕組み。
- モデル
モデルは、データベースのテーブルに対応するクラスです。
モデルクラスのインスタンスは、ひとつのレコードを表すオブジェクトです。
Railsのモデルは、sql文を生成してくれるfindメソッド等を使って、レコードを直感的に扱うことができます。
データベース(テーブル名) |
hoge_fugas |
モデル(クラス名) |
HogeFuga |
モデル(ファイル名) |
hoge_fuga.rb |
単体テスト(ファイル名) |
hoge_fuga_test.rb |
- データベース作成
DBMSへの接続設定
config\database.ymlで設定します。
development:
adapter: mysql
database: appname_development
username: root
password:
host: localhost
encording: utf8
test:
adapter: mysql
database: appname_test
username: root
password:
host: localhost
encording: utf8
production:
adapter: mysql
database: appname_production
username: hoge
password: fuga
host: hoge.fuga.piyo.jp
encording: utf8
- MySQLのデフォルト文字コード設定
MySQLの設定ファイルに文字コードを定義すれば、config\database.ymlでの"encording: utf8"や、データベース作成時の"character set utf8"が不要になります。
# SERVER SECTION
[mysqld]
default-character-set=utf8
skip-character-set-client-handshake
($ NET STOP mysql)
$ NET START mysql
mysql> show variables like "char%";
テーブル作成
$ ruby script\generate model mdlname
- マイグレーション
スクリプトを利用して、テーブルの作成や変更を容易に行う仕組み。
マイグレーションスクリプトのファイル名には通し番号がついており、この番号をもとにバージョン管理されます。
バージョンアップ時はupメソッドが、バージョンダウン時はdownメソッドが実行されます。
- up/downメソッドの中に記述できるメソッドの例
メソッド |
機能 |
create_table/drop_table |
テーブルの作成/削除 |
add_column/remove_column |
フィールドの追加/削除 |
rename_column |
フィールド名の変更 |
change_column |
フィールドの型の変更 |
add_index/remove_index |
インデックスの作成/削除(後述) |
$ rake db:migrate
$ rake db:migrate RAILS_ENV=production
$ rake:db:migrate VERSION=***
マイグレーションのバージョンは、データベース内に作成されるschema_infoテーブルで管理されています。
バージョン番号は、スクリプトの処理が正常に実行されたかどうかに関わらず変更されてしまいますので、スクリプトの記述にミス等があると、バージョン変更ができなくなってしまうことがあります。
その場合は、一度データベースを削除してから再作成し、スクリプトを修正して、再度rake db:migrateを実行しましょう。
-
- インデックス
フィールドにインデックスを作成すると、検索やソートを高速化できます。
レコードの保存のたび、そのフィールドを基準にソートされるからです。
各レコードで値の一意性が高いフィールドに作成すると有効です。
フィクスチャ
- フィクスチャ
データベースの初期状態。
フィクスチャファイルに記述した内容は、いつでもデータベースのデータとして利用することができます。
ただし、フィクスチャの内容がデータベースの状態と矛盾していると、エラーが発生します。
hoge:
id: 1
name: Mr.Hoge
age: 25
fuga:
id: 2
name: Ms.Fuga
age: 24
…
piyo:
id: 30
name: Mr.Piyo
age: 20
- scaffold
scaffoldという仕組みを利用すると、一般的にテーブルの管理で必要とされる機能を一気に作成できます。
ただし、あくまでも開発をサポートするための仕組みであり、scaffoldを利用しなくても開発は可能です。
アプリケーションの仕様に沿って、柔軟に開発していくことが重要です。
$ ruby script\generate scaffold mdlname ctrname
findメソッド
findメソッドの基本形はMdlName.find(条件)です。
@member = Member.find(1)
@nanme = @member.name
@members = Member.find(:all)
his_name = "Mr.Hoge"
his_age = 25
@members = MdlName.find(:all,
:conditions => ["name = ? and age = ?", his_name, his_age])
@members = MdlName.MdlName.find_by_name_and_age(his_name, his_age)
@members = MdlName.find(:all,
:order => "age")
@members = MdlName.find(:all,
:order => "age DESC")
-
-
- all の代わりに first/last を使えば、配列のうち最初/最後のレコードだけ取り出すことができます。
- :conditions => "name = #{name} and age = #{age}" としてはならない理由
ユーザにブラウザのフォームから文字列を入力させる際、SQLインジェクション(危険なSQL文を実行させるようなサーバへの攻撃)の恐れがあります。
ユーザが入力した情報を変数に取得する場合、情報に危険な文字列が含まれていると、それがSQL文として実行されてしまい大変危険です。
「?」を利用して記述すれば、情報をエスケープ(ユーザが入力した情報がそのままSQL文として実行されないようにする処理)してくれます。
-
- 個数制限(:limit/:offsetオプション)
@members = MdlName.find(:all,
:limit => 5,
:offset => 10)
- sql文を直接指定(find_by_sql)
findメソッドに用意されているオプションだけでは複雑すぎる条件などに有効です。
his_name = "Mr.Hoge"
his_age = 25
@members = MdlName.find_by_sql(["select * from members where name = ? and age = ?", his_name, his_age])
メソッド |
機能 |
average(フィールド名) |
平均 |
count |
レコード数 |
maximum(フィールド名) |
最大値 |
minimum(フィールド名) |
最小値 |
sum(フィールド名) |
合計 |