今回実装する機能
投稿機能
目的: ユーザーがリアルタイムで災害状況を共有できる。
1.投稿モデルの作成
投稿に関連するモデルを生成します。
rails g scaffold Post title:string content:text image:string location:string user:references
生成されたマイグレーションファイルを確認し、必要であれば修正してからマイグレーションを実行します。
rails db:migrate
2. 投稿とユーザーの関連付け
Post
モデルにユーザーとの関連を設定します。
class Post < ApplicationRecord
belongs_to :user
has_one_attached :image # 画像アップロード用
validates :title, :content, presence: true
end
User
モデルに関連付けを追加します。
class User < ApplicationRecord
has_many :posts, dependent: :destroy
end
3.画像アップロード機能
画像をアップロードするには、RailsのActive Storageを利用します。Active Storageを有効化するために以下を実行します。
rails active_storage:install
rails db:migrate
投稿フォームに画像アップロード機能を追加します。
app/views/posts/_form.html.erb
を編集します。
<%= form_with(model: post, local: true) do |form| %>
<%= form.label :title %>
<%= form.text_field :title %>
<%= form.label :content %>
<%= form.text_area :content %>
<%= form.label :image %>
<%= form.file_field :image %> <!-- 変更部分 -->
<%= form.label :location %>
<%= form.text_field :location %>
<%= form.submit %>
<% end %>
画像の表示を追加します。
app/views/posts/show.html.erb
で以下を挿入します。
<% if @post.image.attached? %>
<%= image_tag @post.image %>
<% end %>
4. 投稿の編集と削除(投稿者本人のみ)
コントローラに認可ロジックを追加します。
app/controllers/posts_controller.rb
に以下を追記します。
before_action :authenticate_user!
before_action :set_post, only: %i[show edit update destroy]
before_action :authorize_user!, only: %i[edit update destroy]
private
def set_post
@post = Post.find(params[:id])
end
def authorize_user!
redirect_to posts_path, alert: "操作権限がありません。" unless @post.user == current_user
end
5.いいね機能
Like
モデルを作成します。
rails g model Like user:references post:references
rails db:migrate
Post
とUser
に関連を追加します。
# app/models/post.rb
class Post < ApplicationRecord
has_many :likes, dependent: :destroy
end
# app/models/user.rb
class User < ApplicationRecord
has_many :likes, dependent: :destroy
end
# app/models/like.rb
class Like < ApplicationRecord
belongs_to :user
belongs_to :post
end
ルーティングとコントローラを設定します。
config/routes.rb
に以下を追加します。
resources :posts do
resources :likes, only: [:create, :destroy]
end
LikesController
を作成します。
class LikesController < ApplicationController
before_action :authenticate_user!
def create
post = Post.find(params[:post_id])
post.likes.create(user: current_user)
redirect_to post_path(post)
end
def destroy
like = Like.find_by(post_id: params[:post_id], user: current_user)
like.destroy if like
redirect_to post_path(params[:post_id])
end
end
投稿ビューにいいねボタンを追加します。
<% if current_user.likes.find_by(post_id: @post.id) %>
<%= button_to 'いいねを取り消す', post_like_path(@post, current_user.likes.find_by(post_id: @post.id)), method: :delete %>
<% else %>
<%= button_to 'いいね', post_likes_path(@post), method: :post %>
<% end %>
6.コメント機能
Comment
モデルを作成します。
rails g model Comment content:text user:references post:references
rails db:migrate
ルーティングとコントローラを設定します。
config/routes.rb
に以下を追加します。
resources :posts do
resources :comments, only: [:create, :destroy]
end
CommentsController
を作成します。
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
post = Post.find(params[:post_id])
comment = post.comments.new(comment_params)
comment.user = current_user
if comment.save
redirect_to post_path(post), notice: 'コメントを追加しました。'
else
redirect_to post_path(post), alert: 'コメントを追加できませんでした。'
end
end
def destroy
comment = Comment.find(params[:id])
if comment.user == current_user
comment.destroy
redirect_to post_path(comment.post), notice: 'コメントを削除しました。'
else
redirect_to post_path(comment.post), alert: '権限がありません。'
end
end
private
def comment_params
params.require(:comment).permit(:content)
end
end
投稿ビューにコメントフォームとリストを追加します。
<h3>コメント</h3>
<% @post.comments.each do |comment| %>
<p><%= comment.content %> - <%= comment.user.name %></p>
<% if comment.user == current_user %>
<%= link_to '削除', post_comment_path(@post, comment), method: :delete, data: { confirm: '本当に削除しますか?' } %>
<% end %>
<% end %>
<%= form_with(model: [ @post, Comment.new ], local: true) do |form| %>
<%= form.text_area :content, placeholder: 'コメントを追加...' %>
<%= form.submit 'コメントする' %>
<% end %>
今回は以上になります。
参考文献