「バイクの検索サイト」を作ることを目標にRailsを勉強中です。なんとなくバイク一覧とメーカー一覧を作ったものの、バイクにはモデル(シリーズ)と呼ばれるように、2012年モデル、2013年モデル、といった車体があることに気づきました。
設計と言っていいかわからないですが、bikesテーブルを親として、modelsテーブルを子供とする、という形にしようと思います。
そうなると、bikesのidとmodelsのbike_idが紐付いているとなんか外部キー制約でイケてるんだろうなと思い、トライしてみました。
また、外部キー制約には「連鎖参照整合性制約」というお約束をつけることができ、これによって親のbikeがテーブルから削除されると子供のmodelも削除されるということができるようなので、こちらもトライしました。
まずはコントローラーを作っておく(モデルコントローラーのインデックスアクション)。ただぶっちゃけこのコントローラーが必要なのかはよくわかってない。
$ rails g controller models index
モデルを作ります。
$ rails g model Model bike:references model_name:string full_length:integer overall_width:integer height:integer wheel_base:integer ground_clearance:integer seat_height:integer engin_type_id:integer cc:integer gross_vehicle_weight:integer fuel_capacity:integer price:integer image_url01:text image_url02:text image_url03:text
外部キー制約をつけるbikeカラムの型を「references」とするのが味噌のようです。
migrationファイルが作られるので編集します >db/migrate/20180610231850_create_models.rb
class CreateModels < ActiveRecord::Migration[5.2] def change create_table :models do |t| t.references :bike #→こうやって書くと、外部キー制約を持てるbike_idというカラムが作れる t.string :model_name t.integer :full_length t.integer :overall_width t.integer :height t.integer :wheel_base t.integer :ground_clearance t.integer :seat_height t.integer :engin_type_id t.integer :cc t.integer :gross_vehicle_weight t.integer :fuel_capacity t.integer :price t.text :image_url01 t.text :image_url02 t.text :image_url03 t.timestamps end add_foreign_key :models, :bikes, column: :bike_id, on_delete: :cascade, on_update: :cascade #→この行を追加することが重要。add_foreign_keyで外部キー制約をもたせる。子table名、親table名、外部キー制約をもたせる子tableのカラム名。これで勝手にbikesテーブルのidに外部キー制約がかけられる。 end end end
あとはmigrateを実行するだけ。
$ rails db:migrate == 20180610231850 CreateModels: migrating ===================================== -- create_table(:models) -> 0.1460s -- add_foreign_key(:models, :bikes, {:column=>:bike_id}) -> 0.0713s == 20180610231850 CreateModels: migrated (0.2176s) ============================
実際に外部キー制約とCASCADEが設定されているかsequel proで見てみる
これで親のバイクを消すと子供のモデルも消えるようになった。