1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Ruby on Railsでコミュニティ機能を実装しよう:中間テーブルの作成とdeviseを使ったログイン機能の追加

Last updated at Posted at 2023-04-09

目的

タイトルが不自然に凝ってますが、chatGPTと話してるついでに考えてもらいました。
今回はコミュニティ機能を実装します。
ユーザーが複数のコミュニティに参加できるようにモデルを作成したいと思います。
自分の知っている範囲で考えても答えが出てこなかったので、chatGPTに相談したら中間テーブルなるものを知りました。よく分かっていないのでその理解も含め、頑張ります!

今回やること

今回の目標は以下の2つ。

  • ユーザーが複数のコミュニティに参加できるようにモデルを作成
  • ログイン機能を実装

環境

  • windows 10
  • ruby 3.0.4
  • rails 6
  • Bootstrap 5.0.2

いざ出陣

deviseの導入

まず最終的にやりたいこととしては、以下の要件を満たすモデルを作ることです。

  • ユーザーは、複数のコミュニティに参加することができる。
  • コミュニティには、複数のユーザーが参加することができる。

これらの関係を表すために、中間テーブルを作成する必要があると言われたので、最終的なモデルは3つです。

  • Userモデル
  • Communityモデル
  • Membershipモデル

できることからやろう。
まずは、ログイン機能のを実装するためのgemとして device を導入します。

gemfile
# 追加
gem 'devise'
cmd
bundle install
rails generate devise:install   # 初期設定

rails generate devise:install を実行すると、 config/initializers/devise.rbconfig/locales/devise.en.yml が作成され、対応すべきこと?が4つ出てきました。

  1. default_url_options の設定
  2. root_url の設定
  3. flashメッセージの設定
  4. Devise のビューをカスタマイズする

1は無視。
2はすでにやっている。
3と4はやります。

3. flashメッセージの設定

app > views > layouts > application.html.erbに以下のコードを追加して、flashメッセージを出せるようにします。chatGPTにapplication.html.erbのどこに追加すれば聞いたら、警告とは違うコードを追加してましたが、こっちのがかっこ良いしできそうなのでこれでいきます。

app\views\layouts\application.html.erb
  <body>
    <%= yield %>
    <% flash.each do |name, msg| %>
      <%= content_tag :div, msg, class: "alert #{name}" %>
    <% end %>
  </body>

設定ができたかを確認するために、app > controllers > users_controller.rbでflashメッセージを書いてみます。

app\controllers\users_controller.rb
class UsersController < ApplicationController
  def index
    flash[:notice] = "テストメッセージ"
  end
end

image.png
できてますね。神。

4. Devise のビューをカスタマイズする

コマンドプロンプトで以下を実行します。

cmd
rails g devise:views

これで、Deviseによって自動生成されたビューをカスタマイズするためのテンプレートファイルが作成されました。後で確認します。

Userモデルの作成

ログイン機能のあるUserモデルを作成するために以下を実行します。

cmd
rails generate controller users
rails generate devise User
rails db:migrate

すると、config > routes.rbに、以下のように追加されています。
これによってユーザー認証に関わるルーティングが作成されます。

config\routes.rb
Rails.application.routes.draw do
  devise_for :users    # これが追加される
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  resources :users
  root   'users#index'
end

このまま動作確認をすると、 http://localhost:3000/users/sign_in で画面は表示されますが、ログインしていなくても http://localhost:3000/users が開けます。
image.png
ログインしていなければ、 http://localhost:3000/users/sign_in に飛ぶようにしたいので、app > controllers > users_controller.rbに以下を追加します。

app\controllers\users_controller.rb
class UsersController < ApplicationController
  before_action :authenticate_user!    # これを追加
  
  def index
    flash[:notice] = "テストメッセージ"
  end
end

画面がかわいくないのは、さっき用意したテンプレートファイルを編集して後でカスタマイズします。

Userテーブルにカラムを追加

migrationの使い方に苦しんだ...
とりあえず分かったことを箇条書きにする。

  • migrationファイルを rails db:migrate したり rails db:rollback したりしてモデルを変更する。
  • カラムを追加するときのmigrationファイルは、 rails g migration AddDetailsToUsers で作成する。

具体的には、以下のように作業しました。

migrationファイルの作成

cmd
rails g migration AddDetailsToUsers

カラムの追加

db\migrate\yyyymmddhh24miss_add_details_to_users.rb
class AddDetailsToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :username, :string, null: false
    add_column :users, :gender, :string
    add_column :users, :origin_prefecture, :string, null: false
    add_column :users, :residence_prefecture, :string, null: false
    add_column :users, :residence_city, :string, null: false
  end
end

Viewから飛んできた情報を受け取れるようにする。

app\controllers\application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :gender, :origin_prefecture, :residence_prefecture, :residence_city])
  end
end

あとはhtmlの編集で、設定したカラムを画面から登録できるようにします!
以下のコードを、追加したカラム分追記します。

app\views\devise\registrations\new.html.erb
<div class="field">
  <%= f.label :username %><br />
  <%= f.text_field :username, autofocus: true, autocomplete: "username" %>
</div>

出来た。
image.png

Communityモデルの作成

以下を実行。

cmd
rails g model Community eventname:string

eventnameのnullを却下してmigrate

cmd
# 変更前
t.string :eventname

# 変更後
t.string :eventname, null: false
cmd
rails db:migrate

他にもカラム必要だけど、いったん後で。

Membershipモデルの作成

ユーザーとコミュニティの多対多の関係を表す中間テーブルを作成するために、Membershipモデルを作成します。

cmd
rails g model Membership user:references community:references

UserモデルとCommunityモデルに、アソシエーションを定義します。
アソシエーションとは、Railsにおいてモデル間の関係を定義する仕組みのことです。

app\models\user.rb
class User < ApplicationRecord
  has_many :memberships    # これを追加
  has_many :users, through: :memberships    # これを追加
  
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end
app\models\community.rb
class Community < ApplicationRecord
  has_many :memberships    # これを追加
  has_many :users, through: :memberships    # これを追加
end

そしてマイグレーション。

cmd
rails db:migrate

アソシエーションのメゾットには、以下のようなものがあります。
まぁ、読めはしますよね。書けはしないけど。

メソッド名 説明
belongs_to 他のモデルに属することを示す。
has_one 他のモデルと1対1の関係を示す。
has_many 他のモデルと1対多の関係を示す。
has_many through 間に中間モデルを挟んで他のモデルと多対多の関係を示す。

余談

右上の検索ボタンのホバーしたときの文字色、ヘッダーの色と合わせよ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?