アプリにお気に入り機能を実装したいと思ったことはありませんか?
今回は、Railsアプリにお気に入り機能を実装していきます。
実装してみたいと考えているかたは、こちらの記事を参考にしてみてください。
非同期通信の実装は下記の記事を御覧ください!
アプリの開発環境は、以下になります。
- ruby 2.6.5
- rails 6.0.0
- mysql
アプリ作成 ~準備~
まずは、アプリを作成していきます。
アプリの構成としては以下のようになります。
## Users テーブル
| Column | Type |Options |
|--------------------------------------|--------|---------------------------|
| email | string | null: false, unique: true |
| encrypted_password | string | null: false |
## Association
- has_many :posts
- has_many :favorites
## Posts テーブル
| Column | Type | Options |
|-------------------|------------|--------------------------------------------|
| title | string | null: false |
| user | references | null: false, foreign_key: true |
## Association
- belongs_to :user
- has_many :favorites
## Favorites テーブル
| Column | Type | Options |
|-------------------|------------|--------------------------------------------|
| user | references | null: false, foreign_key: true |
| post | references | null: false, foreign_key: true |
## Association
- belongs_to :user
- belongs_to :post
今回はお気に入り機能のアプリなので、”favorite-app“とします。
rails _6.0.0_ new favorite-app -d mysql
アプリを作成したら、次にデータベースを作成しておきます。
rails db:create
アプリ作成 ~実装~
ここから、実装に取り掛かっていきます。
ユーザー管理機能
deviseを使って、ユーザー登録から実装していきます。
Gemfileに以下の記述をしましょう。
gem 'devise'
記述したら、ターミナルで以下のコマンドを実行します。
トップページも作成しておきましょう。
bundle install
rails g devise:install
rails g devise user
rails db:migrate
# トップページの作成
rails g controller posts index
config/routes.rbを以下のように記述しましょう。
Rails.application.routes.draw do
devise_for :users
root 'posts#index' # 追加
end
続いて、viewの記述をしましょう。
posts/index.html.erbを以下のように記述しましょう。
<% if user_signed_in? %>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to 'ログイン', new_user_session_path %>
<%= link_to '新規登録', new_user_registration_path %>
<% end %>
投稿機能
投稿機能を実装していきます。
まずモデルを作成いきます。
ターミナルで以下のコマンドを実行しましょう。
rails g model post title:string user:references
rails db:migrate
ルーティング、コントローラー、モデル、ビューを記述してきます。
以下を参考にしてください。
# config/routes.rb
Rails.application.routes.draw do
devise_for :users
root 'posts#index'
resources :posts, only: [:index, :new, :create]
end
# posts_controller.rb
class PostsController < ApplicationController
# ログインしている人だけが投稿を行えるように[authenticate_user!]を使用
before_action :authenticate_user!, except: :index
def index
@posts = Post.all
end
def new
@post = Post.new
end
def create
Post.create(post_params)
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:title).merge(user_id: current_user.id)
end
end
# user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
end
# post.rb
class Post < ApplicationRecord
belongs_to :user
validates :title, presence: true
end
# posts/index.html.erb
<% if user_signed_in? %>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<%= link_to '投稿ページへ', new_post_path %>
<% else %>
<%= link_to 'ログイン', new_user_session_path %>
<%= link_to '新規登録', new_user_registration_path %>
<% end %>
<div class="post">
<h2>投稿一覧</h2>
<p>↓↓↓</p>
<%= @posts.reverse_each do |post| %>
<div>
<%= post.title %>
<div>
<% end %>
</div>
# posts/new.html.erb
<%= form_with model: @post, local: true do |f| %>
<%= f.text_field :title %>
<%= f.submit '投稿する' %>
<% end %>
サーバーを起動して問題なく投稿できるか確認してみましょう。
rails s
お気に入り機能
お気に入り機能を実装していきましょう。
まずモデルの作成をします。
ターミナルで以下のコマンドを実行しましょう。
rails g model favorite user:references post:references
rails db:migrate
アソシエーションの記述をしていきます。
各モデルにアソシエーションの記述をしましょう。
# user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
has_many :favorites # 追記
end
# post.rb
class Post < ApplicationRecord
belongs_to :user
has_many :favorites # 追記
validates :title, presence: true
end
# favorite.rb
class Favorite < ApplicationRecord
belongs_to :user
belongs_to :post
end
記述することができたら、次にビューを記述していきます。
# posts/index.html.erb
<% if user_signed_in? %>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<%= link_to '投稿ページへ', new_post_path %>
<% else %>
<%= link_to 'ログイン', new_user_session_path %>
<%= link_to '新規登録', new_user_registration_path %>
<% end %>
<div class="post">
<h2>投稿一覧</h2>
<p>↓↓↓</p>
<%= @posts.reverse_each do |post| %>
<div>
<%= post.title %>
# ここから
<% if user_signed_in? && current_user != post.user %>
<% if current_user.favorite_find(post.id) %>
<%= link_to 'お気に入りからはずす', '#' %>
<% else %>
<%= link_to 'お気に入り登録する', '#' %>
<% end %>
<% end %>
# ここまで追記
</div>
<% end %>
</div>
favorite_findはまだ定義されていないメソッドになります。
モデルにメソッドを定義しましょう。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts
has_many :favorites
# 以下を記述
def favorite_find(post_id)
favorites.where(post_id: post_id).exists?
end
end
whereメソッドを使用して、favoritesテーブルにpost_idが存在しているか確認しています。
次に、お気に入り登録と解除の機能を実装します。
コントローラーを作成していきましょう。
ターミナルで以下のコマンドを入力しましょう。
rails g controller favorites create destroy
作成することができたら記述していきます。
以下のように記述しましょう。
# favorites_controller.rb
class FavoritesController < ApplicationController
def create
Favorite.create(user_id: current_user.id, post_id: params[:id])
redirect_to root_path
end
def destroy
favorite = Favorite.find_by(user_id: current_user.id, post_id: params[:id])
favorite.destroy
redirect_to root_path
end
end
ルーティングとビューも記述していきます。
# config/routes.rb
Rails.application.routes.draw do
devise_for :users
root 'posts#index'
resources :posts, only: [:index, :new, :create]
# 以下2行を追加
post 'favorite/:id' => 'favorites#create', as: 'create_favorite'
delete 'favorite/:id' => 'favorites#destroy', as: 'destroy_favorite'
end
# posts/index.html.erb
<% if user_signed_in? %>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
<%= link_to '投稿ページへ', new_post_path %>
<% else %>
<%= link_to 'ログイン', new_user_session_path %>
<%= link_to '新規登録', new_user_registration_path %>
<% end %>
<div class="post">
<h2>投稿一覧</h2>
<p>↓↓↓</p>
<%= @posts.reverse_each do |post| %>
<div>
<%= post.title %>
# ここから
<% if user_signed_in? && current_user != post.user %>
<% if current_user.favorite_find(post.id) %>
# パスの記述を変更
<%= link_to 'お気に入りからはずす', destroy_favorite_path(post.id), method: :delete %>
<% else %>
# パスの記述を変更
<%= link_to 'お気に入り登録する', create_favorite_path(post.id), method: :post %>
<% end %>
<% end %>
# ここまで追記
</div>
<% end %>
</div>
最後に挙動を確認してみましょう。
以下の動画のようになっていれば問題ありません。
簡易的ではありましたが、お気に入り機能を実装していきました。
ぜひ自身のアプリにも実装してみてください。
最後までご覧頂きありがとうございました。
非同期通信の実装は下記の記事を御覧ください!