見出し画像

詳細ページ・削除・編集機能の実装

初めましてこんにちは!すんぎぃです。
SoundReviewというアプリができるまでの流れをやっています。
今回は、詳細ページ・削除・編集機能の実装方法について話していきます。

1.目的

投稿の詳細を見ることができるようにする。
投稿をした人が投稿を取り消したり、内容を変更できるようにする。

2.扱うgem

なし

3.方法

○詳細ページ作成

①routesを以下のように編集します。

Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'items#index'
resources :items ,only: [:index,:new,:create,:show]
  
ends

詳細ページの作成のためshowアクションを追加します。

②投稿一覧ページから詳細ページに遷移できるようにします。
index.html.erbを以下のように編集します。

//省略
<li class='list'>
  <%= link_to item_path(item.id),class:"link" do %>
     <div class='item-info'>
       <%= item.name%>
     </div>
     
     //省略
  <%end%> 
<li>   

パスは、terminalで以下のようにすることで見ることができます。

% rails routes

詳細表示するものを区別するために、パスにはitemのidをパラメーターとして持たせています。

③showアクションをコントローラーに定義していきます。
以下のようにitemsコントローラーにshowアクションを定義します。

class ItemsController < ApplicationController
 before_action :authenticate_user!, except: [:index, :show]
 before_action :set_item, only: [:show]

//省略

 def show
   
 end
 
 private
 def item_params
   params.require(:item).permit(:name, :text, :audio, :category_id, :url, :image, :minicategory).merge(user_id: current_user.id)
 end
 def set_item
   @item = Item.find(params[:id])
 end
end

パラメータとして受け取ったparams[:id]をもとに、詳細表示したいitemをfindメソッドを用いて取得しています。

④詳細ページの作成をしていきます。
app/views/itemsディレクトリにビューファイルにshow.html.erbを作成します。

⑤show.html.erbを以下のように編集します。

    <%= render "shared/header" %>
   
   <div class="item-show">
     <div class="item-box">
       <div class="item-profile">
        <div class="cate-name"> 
          <span class="show-category">Category</span><br/>
          <%if @item.category.name== "映画" %>
           <%= link_to "#{@item.category.name}", "/” ,class: "another-itom" %><br/><p class="mini-name"><%=@item.minicategory%><p>
          <%elsif @item.category.name== "アニメ" %>
           <%= link_to "#{@item.category.name}", "/" ,class: "another-itom" %><br/><p class="mini-name"><%=@item.minicategory%><p>
          <%elsif @item.category.name== "音楽" %>
           <%= link_to "#{@item.category.name}", "/" ,class: "another-itom" %><br/><p class="mini-name"><%=@item.minicategory%><p>
          <%elsif @item.category.name== "本" %>
           <%= link_to "#{@item.category.name}", "/" ,class: "another-itom" %><br/><p class="mini-name"><%=@item.minicategory%><p>
          <%elsif @item.category.name== "その他" %>
           <%= link_to "#{@item.category.name}", "/" ,class: "another-itom" %><br/><p class="mini-name"><%=@item.minicategory%><p>
          <%end%>
        </div>
       
      </div> 
       <h2 class="name">
         <%= @item.name %>
       </h2>
       
       <div class="item-content">
         <div class="item-img-content">
           <%if @item.image.attached? %>
             <%= image_tag @item.image, class: "item-box-img"  %>
           <%else%>
             <%= image_tag 'soundreview2.png', class: "item-box-img"  %>
           <%end%>
         </div>
       </div> 
      
       <div class="item-user">
           
           <div class="profile">
               <% if @item.user.image.attached? %>
                 <%=link_to "/",class:"user-icon4" do %>
                   <%= image_tag @item.user.image, class: "user-icon4" %>
                 <%end%>  
               <% else %>
                 <%=link_to "/" ,class:"user-icon4" do %>
                   <%= image_tag "willy.png", alt: "user-icon", class: "user-icon4" %>
                 <%end%>
               <% end %>
             </div>
           
           <div class="item-user-name">
             <%= link_to @item.user.nickname, "/" %>
           </div> <br/>
       </div> 
       <div>
         <%=@item.created_at.strftime('%Y/%m/%d')%>
       </div>  
         
      
       <div class="item-price-box">
         <audio src= "<%= "#{@item.audio}" %>" controls="" preload="metadata">
                 
         </audio>
         
       </div>
       <%if @item.text.present?%>
       <table class="detail-table">
         <tbody>
           <tr>
             <th class="detail-item">テキストレビュー</th>
             <td class="detail-value detail-text" id="text"><%= @item.text %></td>
           </tr>
         </tbody>
       </table>
      
       <%end%>
        
       <%if @item.url.present?%>
       <div class="url">
         外部URL<br/>
         <div class="item-urll">
           <%=link_to "関連サイトへ", @item.url %>
         </div>  
       </div>
       <%end%>
     </div>
     
    
     <%if @item.category.name== "映画" %>
       <%= link_to "#{@item.category.name}をもっと見る", "/" ,class: "another-item" %>
     <%elsif @item.category.name== "アニメ" %>
       <%= link_to "#{@item.category.name}をもっと見る", "/" ,class: "another-item" %>
     <%elsif @item.category.name== "音楽" %>
       <%= link_to "#{@item.category.name}をもっと見る", "/" ,class: "another-item" %>
     <%elsif @item.category.name== "本" %>
       <%= link_to "#{@item.category.name}をもっと見る", "/" ,class: "another-item" %>
     <%elsif @item.category.name== "その他" %>
       <%= link_to "#{@item.category.name}をもっと見る", "/" ,class: "another-item" %>  
     <%end%>    
   </div>
   
 <%= render "shared/footer" %>

これで詳細ページを表示することができます。

○編集機能の実装

①routesを以下のように編集します。

Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'items#index'
resources :items ,only: [:index,:new,:create,:show,:edit]
  
end

編集機能を実装するためにshowアクションを加えていきます。

②詳細ページから編集ページに遷移できるようにします。
show.html.erbを以下のように編集します。

//省略
<%if @item.url.present?%>
       <div class="url">
         外部URL<br/>
         <div class="item-urll">
           <%=link_to "関連サイトへ", @item.url %>
         </div>  
       </div>
       <%end%>
       
       <%if user_signed_in?%>
       <%if current_user.id==@item.user_id %>
       <div class="edit-btn">
         <div class="edit">
           <%= link_to "レビューの編集", edit_item_path, method: :get, class: "item-red-btn" %>
         </div>  
         
       </div>  
       <%end%>
       <%end%>
 //省略

③editアクションをコントローラーに定義していきます。
以下のようにitemsコントローラーにeditアクションを定義します。

class ItemsController < ApplicationController
 before_action :authenticate_user!, except: [:index, :show]
 before_action :set_item, only: [:show,:edit]

//省略

 def edit
   
 end
 
 private
 def item_params
   params.require(:item).permit(:name, :text, :audio, :category_id, :url, :image, :minicategory).merge(user_id: current_user.id)
 end
 def set_item
   @item = Item.find(params[:id])
 end
end

④編集ページの作成をしていきます。
app/views/itemsディレクトリにビューファイルにedit.html.erbを作成します。

⑤edit.html.erbを以下のように編集します。

<div class="items-sell-contents">
 <header class="items-sell-header">
   <%= link_to image_tag('soundreview.png' , size: '185x50'), "/" %>
 </header>
 <div class="items-sell-main">
   <h2 class="items-sell-title">レビューの情報を入力</h2>
   <%= render 'shared/error_messages', model: @item %>
   <%= form_with model:@item, local: true do |f| %>
   <div class="items-detail">
     <div class="weight-bold-text">
     カテゴリー
     <span class="indispensable">*必須</span>
     </div>
     <div class="form">
       
       <%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"select-box", id:"item-category"}) %>
     </div>
     <div class="new-items">
     <div class="weight-bold-text">
       サブカテゴリー
     </div>
     <%= f.text_area :minicategory, class:"items-text", id:"item-name" %>
   </div> 
   </div>    
   <div class="img-upload">
     <div class="weight-bold-text">
       レビュー画像
       
     </div>
     <div class="click-upload">
       <p>
         クリックしてファイルをアップロード
       </p>
       <%= f.file_field :image, id:"item-image" %>
     </div>
   </div>
   <div class="new-items">
     <div class="weight-bold-text">
       作品名<span class="counter">(40文字まで)</span>
       <span class="indispensable">*必須</span>
     </div>
     <%= f.text_area :name, class:"items-text", id:"item-name" %>
   </div>  
   <div class="sound-upload">
     <div class="weight-bold-text">
       音声レビュー
       <span class="indispensable">*必須</span>
     </div>
     <div class="click-upload">
       <p>
         クリックしてファイルをアップロード
       </p>
       <%= f.file_field :audio, id:"item-sound" %>
     </div>
     
   </div>
   <div class="new-items">
     <div class="items-explain">
       <div class="weight-bold-text">
         文字レビュー
       </div>
       <%= f.text_area :text, class:"items-text", id:"item-info"%>
     </div>
   </div>
   <div class="item-url">
     <div class="weight-bold-text">
       作品URL
       
     </div>
     <%= f.text_area :url, class:"url", id:"item-name",class:"url" %>
   </div>  
   <div class="sell-btn-contents">
     <%= f.submit "投稿する" ,class:"sell-btn" %>
     <%=link_to 'もどる', item_path(@item.id), class:"back-btn" %>
   </div>
   
 </div>
 <% end %>
 <footer class="items-sell-footer">
   <%= link_to image_tag('soundreview.png' , size: '185x50'), "/" %>
   <p class="inc">
     ©︎SoundReview,Inc.
   </p>
 </footer>
</div>

⑥updateアクションのルーティングを設定します。
routesを以下のように編集します。

Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'items#index'
resources :items ,only: [:index,:new,:create,:show,:edit,:update]
  
end

更新をしたいのでupdateアクションを追加します。

terminalでrails routesを行い確認すると投稿内容などの部分的な更新をするので、updateアクションにはPATCHというHTTPメソッドが使用されます。

⑦updateアクションをコントローラーに定義していきます。
以下のようにitemsコントローラーにupdateアクションを定義します。

class ItemsController < ApplicationController
 before_action :authenticate_user!, except: [:index, :show]
 before_action :set_item, only: [:show,:edit,:update]

//省略

def update
   if @item.update(item_params)
     redirect_to item_path(@item.id)
   else
     render :edit
   end
 end
 
 private
 def item_params
   params.require(:item).permit(:name, :text, :audio, :category_id, :url, :image, :minicategory).merge(user_id: current_user.id)
 end
 def set_item
   @item = Item.find(params[:id])
 end
end

これで実際に編集をすることができるようになりました。

○削除機能の実装

①destroyアクションのルーティングを設定します。
routesを以下のように編集します。

Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'items#index'
resources :items ,only: [:index,:new,:create,:show,:edit,:update,:destroy]
  
end

resourcesは、7つのアクションをまとめてルーティングの設定ができるので7つのアクションすべてを記述した今、only以下は不要になりました。
そのため以下のように編集することができます。

Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'items#index'
resources :items 
end

②詳細ページから投稿を削除できるようにします。
show.html.erbを以下のように編集します。

//省略
<%if @item.url.present?%>
       <div class="url">
         外部URL<br/>
         <div class="item-urll">
           <%=link_to "関連サイトへ", @item.url %>
         </div>  
       </div>
       <%end%>
       
       <%if user_signed_in?%>
       <%if current_user.id==@item.user_id %>
       <div class="edit-btn">
         <div class="edit">
           <%= link_to "レビューの編集", edit_item_path, method: :get, class: "item-red-btn" %>
         </div>  
         <div class="delete">
           <%= link_to "削除", item_path, method: :delete, class:"item-destroy" %>
         </div>
       </div>  
       <%end%>
       <%end%>
 //省略

削除するものを区別するために、削除ボタンのパスにはitemのidをパラメーターとして持たせています。
HTTPメソッドは、DELETEというHTTPメソッドを指定しています。

③destroyアクションをコントローラーに定義していきます。
以下のようにitemsコントローラーにdestroyアクションを定義します。

class ItemsController < ApplicationController
 before_action :authenticate_user!, except: [:index, :show]
 before_action :set_item, only: [:show,:edit,:update,:destroy]

//省略

 def destroy
   @item.destroy
   redirect_to root_path
 end
 
 private
 def item_params
   params.require(:item).permit(:name, :text, :audio, :category_id, :url, :image, :minicategory).merge(user_id: current_user.id)
 end
 def set_item
   @item = Item.find(params[:id])
 end
end

パラメーターで受け取ったparams[:id]を元に削除したいitemをfindメソッドを用いて取得しています。そして、そのitemをdestroyメソッドで削除します。

これで削除機能は、完成です。

○cssファイルの追加
app/assets/stylesheets/shared以下にファイルを配置します。

4.まとめ

以上で詳細ページ・削除・編集機能の実装は、完成です。
少しだけ違いますが以下のように表示されたらOK!です。

画像1


ありがとうございました。

5.過去記事


この記事が気に入ったらサポートをしてみませんか?