Ruby on Railsで外部キー設定
Ruby on Railsで外部キー設定
スムーズに行くかと思いきや、地味にいろいろやることがある。
ちょっとRailsを過信しすぎたかも。
作りたいテーブルのリレーションについて
アニメテーブルの1レコードに各話テーブルの複数レコードが紐付く
やったこと
各モデルクラスおよびテーブル作成
- アニメモデル作成
$ rails generate scaffold anime title:string anime_image_url:string hash_tag:string
- 各話モデル作成
$ rails generate scaffold chapter chapter:integer title:string start_time:timestamp end_time:timestamp tweet_collect_start_flg:boolean tweet_collect_end_flg:boolean anime:references
- マイグレーションファイル確認
モデル作成コマンドでは「anime:references」と指定しているが、作成されるテーブルのカラムとしては「anime_id」となるので注意。
$ view db/migrate/20130427141102_create_chapters.rb class CreateChapters < ActiveRecord::Migration def change create_table :chapters do |t| t.integer :chapter t.string :title t.timestamp :start_time t.timestamp :end_time t.boolean :tweet_collect_start_flg t.boolean :tweet_collect_end_flg t.references :anime t.timestamps end add_index :chapters, :anime_id end end
- モデルクラス確認
モデル作成コマンドでの「anime:references」により「belongs_to :anime」が自動追加されている。
$ view app/models/chapter.rb class Chapter < ActiveRecord::Base belongs_to :anime attr_accessible :chapter, :end_time, :start_time, :title end
- マイグレーション実施
$ rake db:migrate
外部キー制約補助のためのGem「foreigner」を導入
- インストール
$ vi Gemfile gem 'foreigner' $ sudo bundle install
- マイグレーションファイル修正
$ vi db/migrate/20130427141102_create_chapters.rb class CreateChapters < ActiveRecord::Migration def change create_table :chapters do |t| t.integer :chapter t.string :title t.timestamp :start_time t.timestamp :end_time t.boolean :tweet_collect_start_flg, null:false, :default => false t.boolean :tweet_collect_end_flg, null:false, :default => false # ついでに外部キーにNOT NULL制約を付与 t.references :anime, null: false # 下記行を追加。 # 「dependent: :delete」により親データが削除された際に子データも自動で削除させる。 t.foreign_key :animes, dependent: :delete t.timestamps end add_index :chapters, :anime_id end end
- マイグレーション再実施
$ rake db:migrate:redo
- 各話テーブルのanime_idに外部キー制約が設定されていることを確認。
その他の要修正ファイルについて
- Modelクラスについて、scaffold時に「references」を使用したことにより特殊な項目と判断され「anime_id」が追加されてない。
アプリ動作時に項目が見つからず正常に動作しないため項目を追加
$ vi app/models/chapter.rb class Chapter < ActiveRecord::Base belongs_to :anime attr_accessible :chapter, :end_time, :start_time, :title, :anime_id end
- Viewのerbファイルについて、本来項目名が「anime_id」であるべきところ「anime」となっている。アプリ動作時に項目が見つからず正常に動作しないため修正
$ vi app/views/chapters/_form.html.erb <div class="field"> <%= f.label :anime_id %><br /> <%= f.text_field :anime_id %> </div> <% end %>