テーブル間での連携
テーブルとテーブルを結合してみる。
道具には作った人がいるだろうということで、creatorテーブルを追加。
まずは、新しいテーブルをscaffoldでcreateする。
>ruby script/generate scaffold creator name:string
「db/migrate/003_create_creators.rb」が出来上がってるので、
>rake db:migrate
でテーブルを生成。
「http://localhost:3000/creators」からデータをちょこちょこ追加してあげると、
Name smith Show Edit Destroy herbalist Show Edit Destroy
こんな感じに。
smithは鍛治屋、herbalistは薬草師のこと。
でもって、このcreatorテーブルと、itemテーブルを繋ぐために、
itemテーブルに、creator_idフィールドを追加する。
migrationファイルをgenerateすると、
>ruby script/generate migration AddItemsCreatorID
「db/migrate/004_add_items_creator_id.rb」ができあがるので、
class AddItemsCreatorId < ActiveRecord::Migration def self.up add_column :items, :creator_id, :integer end def self.down remove_column :items, :creator_id, :integer end end
こんな感じで、itemテーブルにcreator_idフィールドを追加する記述をする。
最後に、
>rake db:migrate
で、DB生成完了。
>sqlite3 db/development.sqlite3
で中身を見てみると、
sqlite> .table creators items schema_info
ちゃんとcreatorsテーブルが生成されていて、
sqlite> .schema CREATE TABLE creators ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255) DEFAULT NULL, "created_at" datetime DEFAULT NULL, "updated_at" datetime DEFAULT NULL ); CREATE TABLE items ( "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255) DEFAULT NULL, "price" integer DEFAULT NULL, "created_at" datetime DEFAULT NULL, "updated_at" datetime DEFAULT NULL, "number_of_times" integer, "creator_id" integer ); CREATE TABLE schema_info (version integer);
itemsテーブルには、creator_idも追加されてるのが確認できる。
でもって、テーブルを結合するのに、
「/app/models/creator.rb」に
class Creator < ActiveRecord::Base has_many :items end
「/app/models/item.rb」に
class Item < ActiveRecord::Base belongs_to :creator end
を追記する。
creatorは、itemを複数持つので複数形、itemは、creatorが1つ(1人)だけなので単数形なのに注意。
あとはitemsビューのerbファイルに、creatorのidとnameを表示と修正できるようにちょこちょこっとコード追加。
ひとまずcreator_idはidを手入力でよしとする。
(鍛治屋は1、薬草師は2)
でもって、indexは、
<td><%=h item.name %></td> <td><%=h item.price %></td> <td><%=h item.number_of_times %></td> <td><%=h item.creator_id %></td> <td><%=h item.creator.name %></td> <td><%= link_to 'Show', item %></td> <td><%= link_to 'Edit', edit_item_path(item) %></td> <td><%= link_to 'Destroy', item, :confirm => 'Are you sure?', :method => :delete %></td>
てな具合で、idとnameを表示するようにする。
あとは、「http://localhost:3000/items」を見ると、
Name Price Number of times Creator id Creator name ポーション 100 1 2 herbalist Show Edit Destroy 毒消し 80 1 2 herbalist Show Edit Destroy ナイフ 1000 100 1 smith Show Edit Destroy ソード 2000 500 1 smith Show Edit Destroy
となる。
テーブルを関連付けると、itemsテーブルから"."繋ぎでcreatorsテーブル
を参照できるようになる。
fieldを追加してみる
アイテムデータが出来上がったが、道具というものは使用回数があるわけです。
ということで、各アイテムに使用回数のデータも持たせてみる。
fieldの追加は、
>ruby script/generate migration AddNumberOfTimes
で、migrationファイルをgenerate。
新しく「db/migrate/002_add_number_of_times.rb」なるものが生成されるので、
class AddNumberOfTimes < ActiveRecord::Migration def self.up add_column :items, :number_of_times, :integer end def self.down remove_column :items, :number_of_times, :integer end end
中身をこんな具合に修正してから、
>rake db:migrate
で、データベースを再生成。
「http://localhost:3000/items」を覗くと、変化なし。
っと、ビューを修正しないと当然だわな。
ということで「app/veiws/items」以下のerbファイルを使用回数に対応するように追記。
Editアクションでちょこちょことアイテムデータを修正すると、
Name Price Number of times ポーション 100 1 Show Edit Destroy 毒消し 80 1 Show Edit Destroy ナイフ 1000 100 Show Edit Destroy ソード 2000 500 Show Edit Destroy
てな具合に、アイテムの使用回数のフィールドが追加されてるのが確認できる。
railsコマンドを使ってみる
helpも読んだので、早速使ってみる。
>rails test1
でディレクトリ作成開始。
特に必要を感じないのでオプションは無し。
--quietオプションで表示を抑制してないので、作成ディレクトリ・ファイルがずらずらと表示される。
create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create config/initializers create db create doc create lib create lib/tasks create log create public/images create public/javascripts create public/stylesheets create script/performance create script/process create test/fixtures create test/functional create test/integration create test/mocks/development create test/mocks/test create test/unit create vendor create vendor/plugins create tmp/sessions create tmp/sockets create tmp/cache create tmp/pids create Rakefile create README create app/controllers/application.rb create app/helpers/application_helper.rb create test/test_helper.rb create config/database.yml create config/routes.rb create public/.htaccess create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/boot.rb create config/environment.rb create config/environments/production.rb create config/environments/development.rb create config/environments/test.rb create script/about create script/console create script/destroy create script/generate create script/performance/benchmarker create script/performance/profiler create script/performance/request create script/process/reaper create script/process/spawner create script/process/inspector create script/runner create script/server create script/plugin create public/dispatch.rb create public/dispatch.cgi create public/dispatch.fcgi create public/404.html create public/422.html create public/500.html create public/index.html create public/favicon.ico create public/robots.txt create public/images/rails.png create public/javascripts/prototype.js create public/javascripts/effects.js create public/javascripts/dragdrop.js create public/javascripts/controls.js create public/javascripts/application.js create doc/README_FOR_APP create log/server.log create log/production.log create log/development.log create log/test.log
1割程度しか、なんのためのディレクトリ・ファイルかわからないけども、気にしない。
そのうち把握できるでしょう、たぶん。
railsコマンドのhelpを見てみる
使い方は、
>rails アプリのディレクトリ名 [options]
まあ、これだけ知ってれば問題ないんだけども、helpは一度読んでおいたほうがいいよなぁってことでhelpも見てみる。
以下、optionsの意味。
-r, --ruby=path
Rubyのインストールpath指定。
デフォルトpathは、c:/ruby/bin/ruby
Railsを使うなら素直にCドライブ直下にRubyをインストールしとくのが無難ぽい。
実装の都合でRubyのverを固定したいときとかにうれしいオプションかな?
-d, --database=name
使用するデータベース指定。
選択肢として、MySQL/Oracle/PostgreSQL/SQLite2/SQLite3。
helpではデフォルトがMySQLとなっているが、Rails2.0.2以降はSQLite3がデフォルトのはず。
-f, --freeze
vender/railsにRailsを凍結させる。
実行させるとvender/railsにRails関係のファイルがまとまってコピーされる。
完成したアプリがRailsのverupなどで動作しなくなる、といったのを避けるためにRailsのverが固定できるぽい。
-v, --version
お約束のver表示。
ちなみに、うちの環境は「Rails 2.0.2」
-h, --help
これまたお約束のhelp表示。
-p, --pretend
実行するが変更は加えない。
要は雛形作成とかでエラーがでたりしないかのお試しぽい。
ディレクトリ・ファイル作成してるようにみえるが実際はなにも作成していない。
--force
すでに存在してるファイルを上書きする。
やり直したくなったときに強制上書きするのか?
そこまでするなら、それこそrailsコマンドで新しいアプリ作成したほうがいいような気もするが。
-s, --skip
すでに存在してるファイルをスキップする。
この場合のスキップは、上書き処理をスキップということだろうか?
--force同様、使う場面が思いつかない。
-q, --quiet
表示を避ける。
雛形作成時なんかにズラズラとファイル名を表示しなくなる。
表示はスッキリするがほんとに処理できてるのか不安になる。
-t, --backtrace
エラー時にバックトレースを出力してくれる。
railsコマンドでエラーなんて、ファイル書き込み権限の有無とかくらいしか思いつかないけども、どんなときに役に立つんだろ?
-c, --svn
Subversionを使ってファイルを修正する?
Subversion使ったことがないのでよくわからず。
大規模な開発だとうれしいのだろうか?
とりあえず、普段使いそうなoptionはなさげかな。
ひとまず1から動くところまで作ってみる
そろそろhelpとにらめっこするのも飽きてきたので、データベースを操作するところまで作ってみる。
まずは、ディレクトリを作成。
>rails test1
カレントディレクトリ移動。
>cd test1
でもって、scaffoldのgenerate。
>ruby script/generate scaffold item name:string price:integer
- app/controllers/items_controller.rb
- app/models/item.rb
- app/views/items/index.html.erb
- app/views/items/show.html.erb
- app/views/items/edit.html.erb
- app/views/items/new.html.erb
- db/migrate/001_create_items.rb
その他もろもろが生成されてるのを確認。
もろもろは何に使うのかよく分かってないので、とりあえず放置。
次に、db/migrate/001_create_items.rb(migrationファイル)からデータベースを生成。
>rake db:migrate
SQLiteはファイルベースのデータベースなので、db/development.sqlite3というファイルが生成される。
デフォルトのdevelopment.sqlite3という名前が気に入らない場合は、config/database.yml内でファイル名は指定可能。
以上終了。
あとは、サーバを稼動させて挙動を見てみる。
ruby script/server
scaffoldでindexビューは生成されているので、ブラウザで「http://localhost:3000/items」につないで見ると、それっぽいのが表示される。
indexビューの、NewItemリンクからアイテムデータをもりもりと追加してあげると、
Name Price ポーション 100 Show Edit Destroy 毒消し 80 Show Edit Destroy ナイフ 1000 Show Edit Destroy ソード 2000 Show Edit Destroy
てな具合で登録される。
Showで詳細、Editで修正、Destroyで削除。
見た目はともかくこれだけでデータベースの管理が可能になるのは楽チン。
scaffoldをgenerateしてみる
とりあえず、コントローラとscaffoldがgenerateできれば、簡単なアプリなら作れそうかな?
scaffoldは、直訳すると「土台」
なんで土台か分からないけども、データベースへのレコード追加/削除/修正できるものが自動で生成されるらしい。
Rails2.0以降は、scaffoldのgenerateで、modelもmigrationも生成されるようなので楽になったらしい。
なにがどう楽になったのかはサッパリだけど、楽になってるなら楽な方を使っちゃう。
使い方は、
>ruby script/generate scaffold ModelName [field:type, field:type]
helpだと抜けているけども、optionは
>ruby script/generate scaffold [options] ModelName [field:type, field:type]
のモヨウ。
option
お約束の
- -v, --version
- -h, --help
- -p, --pretend
- -f, --force
- -s, --skip
- -q, --quiet
- -t, --backtrace
- -c, --svn
に加えて、
- --skip-timestamps
- 自動で追加される作成日時・更新日時のfieldを追加しない
- --skip-migration
- migrationファイルを生成しない
といったoptionもある。
field:type
- field
- テーブルの項目
- type
- 項目のタイプ
を、scaffoldをgenerateする時点で指定しないといけないらしい。
指定しなくてもエラーとかは出ないけど、中身のないtableがデータベースに作成されるだけ。
あとからfieldの追加はできるだろうけども、二度手間になるのでココで指定しちゃうほうが賢い。
具体的には、
name:string comment:text weight:integer ...
てな具合。
typeの種類はよくわからないけども、いろいろあるみたい。
scaffoldをgenerateすると、
- コントローラー
- ビュー
- モデル
- migrationファイル
- その他もろもろ
が生成される。
generateのヘルプを読んでみる
初心者はまずはhelpから。
>ruby script/generate generator [options] [args]
てな具合で使う。
generator
イロイロあるようで、
- controller
- コントローラ&ビュー生成
- integration_test
- 統合テスト生成?
- mailer
- メーラー&ビュー生成
- migration
- データベースのmigration生成?
- model
- モデル生成
- observer
- observer生成?
- plugin
- プラグイン生成?
- resource
- リソース関係のなんかを生成?
- scaffold
- scaffold生成
- session_migration
- 意味不明(ノ∀`)
なんかがあるらしい。
controller/model/scaffoldあたりしか分からない。
ま、そのうち分かってくるでしょう。
あとなんかカスタムgeneratorなんてものも作れるモヨウ。
まあ、まずはBuiltinのgeneratorを使えるようになればいいので、そこらへんはあとの楽しみということで。
option
railsコマンドと似てる。
- -v, --version
- ver情報表示
- -h, --help
- help表示
- -p, --pretend
- 実行するが変更しないコマンドテスト
- -f, --force
- 強制上書
- -s, --skip
- スキップ
- -q, --quiet
- 無言
- -t, --backtrace
- バックトレース
- -c, --svn
- Subversion
ちょっと気になったのが、forceオプション。
railsコマンドは「-f」がなかったのにgenerateコマンドには短縮名がある。
で、ちょっとrailsコマンドで-fオプションを使ってみると、
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/core_ext/kernel/agnostics.rb:7:in ``': Exec format error - rake rails:freeze:gems (Errno::ENOEXEC)
なんてことを言われる。
ちなみに、--forceオプションは問題なく実行完了する。
generateコマンドは-fでも--forceでも問題なく実行完了するから、railsコマンドの-fオプションはなんかおかしいのかも?
素直に--forceオプションを使えってことだな。