0
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?

地域防災サイトを作成する記録(第3回)

Posted at

今回実装する機能

投稿機能
目的: ユーザーがリアルタイムで災害状況を共有できる。

1.投稿モデルの作成

投稿に関連するモデルを生成します。

bash
rails g scaffold Post title:string content:text image:string location:string user:references

生成されたマイグレーションファイルを確認し、必要であれば修正してからマイグレーションを実行します。

bash
rails db:migrate

2. 投稿とユーザーの関連付け

Postモデルにユーザーとの関連を設定します。

app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user

  has_one_attached :image # 画像アップロード用
  validates :title, :content, presence: true
end

Userモデルに関連付けを追加します。

app/models/user.rb
class User < ApplicationRecord
  has_many :posts, dependent: :destroy
end

3.画像アップロード機能

画像をアップロードするには、RailsのActive Storageを利用します。Active Storageを有効化するために以下を実行します。

bash
rails active_storage:install
rails db:migrate

投稿フォームに画像アップロード機能を追加します。
app/views/posts/_form.html.erbを編集します。

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で以下を挿入します。

app/views/posts/show.html.erb
<% if @post.image.attached? %>
  <%= image_tag @post.image %>
<% end %>

4. 投稿の編集と削除(投稿者本人のみ)

コントローラに認可ロジックを追加します。
app/controllers/posts_controller.rbに以下を追記します。

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モデルを作成します。

bush
rails g model Like user:references post:references
rails db:migrate

PostUserに関連を追加します。

bush
# 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に以下を追加します。

config/routes.rb
resources :posts do
  resources :likes, only: [:create, :destroy]
end

LikesControllerを作成します。

app/controllers/likes_controller.rb
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

投稿ビューにいいねボタンを追加します。

app/views/posts/show.html.erb
<% 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モデルを作成します。

bash
rails g model Comment content:text user:references post:references
rails db:migrate

ルーティングとコントローラを設定します。
config/routes.rbに以下を追加します。

config/routes.rb
resources :posts do
  resources :comments, only: [:create, :destroy]
end

CommentsControllerを作成します。

app/controllers/comments_controller.rb
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

投稿ビューにコメントフォームとリストを追加します。

app/views/posts/show.html.erb
<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 %>

今回は以上になります。

参考文献

0
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
0
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?