目次
開発環境
- Ruby:version 3.1.2
- Ruby on Rails:version 7.0.4
- Visual Studio Code:version 1.73.0
- OS:Windows10
Ruby on Railsでアソシエーションの実装手順
Ruby on Railsではモデルの関連付けを行うことにより、より直感的にコードが書きやすくなります。
今回はメモアプリの作成で使用した「アソシエーション」のコードを用いて解説していきます。
アソシエーションでモデルの関連付けを行うカラムの作成
まずはアソシエーションでモデルの関連付けを行うカラムの作成をしていきます。
1 | rails g migration add_column_to_memos |
マイグレーションファイルを作成できたら、テーブルにカラムを追加するコードを記述します。
1 2 3 4 5 | class AddColumnToMemos < ActiveRecord::Migration[7.0] def change add_column :memos, :user_id, :integer end end |
add_columnで何のテーブルにカラムを追加するのかを指定することができ、その後にカラム名とデータ型を指定するという形になります。
マイグレーションファイルの作成と記述が完了しましたら、マイグレーションファイルをDBへ反映します。
1 | rails db:migrate |
「memo_app\db\schema.rb」のmemosテーブルにuser_idが反映されていれば成功です。
アソシエーションによる1対多の関連付け
次にアソシエーションによる1対多の関連付けをメモモデルに行います。
1 2 3 4 5 6 7 | class Memo < ApplicationRecord belongs_to :user, class_name: "User", foreign_key: "user_id" validates :user_id, presence: true validates :title, presence: true, length: { minimum: 2, maximum: 32 } validates :description, presence: true, length: { minimum: 2, maximum: 140 } end |
今回はuser_idのカラムを追加しているため、空白は許可しないというバリデーションを追加しています。
メモモデルからユーザーモデルを参照した場合は1対多の関係になるため、belongs_toというメソッドでメモモデルにあるuser_idがユーザーモデルの主キーであるidと関連付けているという処理をしています。
「モデル名_id」となっていれば省略できますが、今回はあえて厳密に明示する方法を知っていただきたいため、class_nameにはモデル名、foreign_keyには関連づいている外部キーを明示しています。
アソシエーションによる多対1の関連付け
次にアソシエーションによる多対1の関連付けをメモモデルに行います。
1 2 3 4 5 6 7 | class User < ApplicationRecord has_many :memos, class_name: "Memo", foreign_key: "user_id" validates :name, presence: true, length: {minimum:2, maximum:32} validates :email, presence: true, uniqueness: true validates :password, presence: true, format: {with: /^[0-9a-zA-Z]+$/, multiline: true} end |
ユーザーモデルからメモモデルを参照した場合は多対1の関係になるため、has_manyというメソッドでユーザーモデルにあるidがメモモデルの外部キーuser_idと関連付けているという処理をしています。
メモモデルと同様に省略せずにclass_nameにはモデル名、foreign_keyには関連づいている外部キーを明示しています。
アソシエーションによるデータ取得
次にコントローラーでアソシエーションによるデータ取得を行います。
4 5 6 7 | def index @memo_new = Memo.new @memos = @current_user.memos end |
ログインしているユーザーのみの情報が一覧に表示されるようにするため、@memosには@current_user.memosを代入しています。
アソシエーションによってモデル同士が関連づいているため、ユーザーモデルで指定した「ユーザーインスタンス.memos」でユーザーに紐づいたデータ取得が可能になります。
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | def ajax_create @memo_new = Memo.new(memos_params) @memo_new.user_id = @current_user.id @memos = @current_user.memos if @memo_new.save flash.now[:notice] = "メモの保存に成功しました。" else flash.now[:alert] = "メモの保存に失敗しました。" end end def search seach_word = params[:word] @memos = @current_user.memos.where("title LIKE ? or description LIKE ?", "%#{seach_word}%", "%#{seach_word}%") if @memos.count > 0 flash.now[:notice] = "#{@memos.count}件のメモが見つかりました。" else flash.now[:alert] = "#メモが見つかりませんでした。" end end private def memos_params params.require(:memo).permit(:title, :description, :user_id) end end |
ログインユーザーが投稿したメモだとわかるように、memosテーブルに追加したuser_idも保存されるように処理をしています。
また、ajax_createでは、indexアクションと同様に@memosにログインユーザーに紐づいたメモのデータ取得ができるように「ユーザーインスタンス.memos」としています。
おわりに
Ruby on Railsでアソシエーションの実装について解説してきましたが、いかがだったでしょうか。
最初はアソシエーションによるリレーションは難しいかもしれせんが、モデル同士の関連付けがわかるようになれば、データベースの設計やプログラムの処理もやりやすくなるかと思います。
是非、基本的な1対多や多対1のモデルの関連付けに挑戦してみてください。