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