【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のモデルの関連付けに挑戦してみてください。

【Ruby on Rails】簡単なメモアプリの作成|アソシエーションによるモデル同士のリレーションを実装 | いっしー@Webエンジニア