LIFE

Adminアカウントで商品を追加する【いせ日記】

今日も【いせ日記】を書いていきます。

今日の作業はこんな感じになってます!

今日やること
・Adminアカウントがログインしたら/adminsのページにいくようにする。
・Admin画面から新しく商品を登録できるようにする(Userからは商品の詳細だけを見れるようにする)

昨日の作業がコントローラーとビューの作成の途中で終わっているので、続きから始めていきます。

作業手順

コントローラーとビューの作成

$rails g controller admins/toppages index
class Admins::ApplicationController < ApplicationController
end
class Admins::ToppagesController < Admins::ApplicationController
  def index
  end
end

ここからコントローラーとビューにコードを追加していきます!

まずはAdminアカウントでログインしたときのナビゲーションバーが下記のようになってしまっているので、ナビゲーションバーを変えなくてはいけないですね。

<header class="mb-4">
  <nav class="navbar navbar-expand-sm navbar-light p-4"style="background-color: #e3f2fd">
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse justify-content-end" id="navbarSupportedContent">
      <ul class="navbar-nav">
        <% if user_signed_in? %>
              <li class="nav-item dropdown">
                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown"></a>
                <ul class="dropdown-menu dropdown-menu-right">
                  <li class="dropdown-divider"></li>
                  <li class="dropdown-item"><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></li>
                </ul>
              </li>
        <% elsif admin_signed_in? %>
              <li class="nav-item dropdown">
                <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown"></a>
                <ul class="dropdown-menu dropdown-menu-right">
                  <li class="dropdown-divider"></li>
                  <li class="dropdown-item"><%= link_to "ログアウト", destroy_admin_session_path, method: :delete %></li>
                </ul>
              </li>
        <% else %>
          <li class="nav-item"><%= link_to 'Signup', new_user_registration_path, class: 'nav-link' %></li>
          <li class="nav-item"><%= link_to 'Login', new_user_session_path, class: 'nav-link' %></li>
        <% end %>
      </ul>
    </div>
  </nav>
</header>

<% elsif admin_signed_in? %>を追加することでAdminアカウントのログアウト機能をナビゲーションバーに追加することできました。

Adminに商品登録機能をつける

admin/products/newというのを作りたいため、productadminreferencesをつけてます。しかし、productsのマイグレーションファイルをadminより先に作ってしまっているため、ファイルの順番を入れ替える必要があります。そのため、下記のように日付を変えてあげると、順番を変更できます。

<before>
20200913131359_create_products.rb
20201009140157_devise_create_admins.rb
⬇️
<after>
20200909140157_devise_create_admins.rb
20200913131359_create_products.rb
class CreateProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|
      t.references :admin, foreign_key: true
      t.references :user, foreign_key: true
      t.string :name, :null => false
      t.text :description, :null => false
      t.integer :price, :null => false

      t.timestamps
    end
  end
end

これでproductsadminreferencesをつけられました。

このままだとマイグレーションができないので、一旦データベースをリセットしていきます。

$ rails db:migrate:reset

無事マイグレーションができましたら、また再度アカウントを作ります。

$ rails db:seed

アカウントが無事作られたら、モデルの関連性を追加します。

class Admin < ApplicationRecord
  has_many :products, dependent: :destroy
end

class Product < ApplicationRecord
  belongs_to :admin
end

モデルに関連性ができたらコントローラーを作成していきます。

そのまえにルーティングの設定をします。

ルーティングの設定

Rails.application.routes.draw do
devise_for :admins
devise_for :users
  root to: "products#index"
  
  resources :products, only: [:show] do
    scope module: :products do
      resources :add_to_carts, only: [:create]
      resources :delete_in_carts, only: [:create]
    end
  end
      
  resource :cart, only: [:show] 
  
  resource :charge, only: [:create]

   namespace :admins do
      root to: "toppages#index"
      resources :products, only: [:new, :create]
   end
end

adminsの配下にproductsを置くことができました。それでは、app/admins/products_controller.rbをを作成していきます。

class Admins::ProductsController < Admins::ApplicationController
end

既にadmins/applicationControllerは作成しているので、class Admins::ProductsController < ApplicationControllerではなく、class Admins::ProductsController < Admins::ApplicationControllerとなります。

それではこのcontrollerで商品登録をし、元々あるproductscontrollerからnewcreateを移します。

class ProductsController < ApplicationController
  
  def index
    @products = Product.order(id: :desc).page(params[:page]).per(10)
  end

  def show
    @product = Product.find(params[:id])
  end
end
class Admins::ProductsController < Admins::ApplicationController
  def new
    @product = current_admin.products.build
  end
  
  def create
    @product = current_admin.products.build(product_params)
      if @product.save
          flash[:success] = "Productが正常に作成されました"
          redirect_to root_path
      else
          flash.now[:danger] = "Productが正常に再生されませんでした"
          render :new
      end
  end
  
  private
  
  def product_params
      params.require(:product).permit(:name, :description, :price, :image)
  end
end

current_userの部分を全てcurrent_adminに変更しました。

ビューの作成

<h1>新規商品の追加</h1>

<%= simple_form_for [:admins,@product] do |f| %>
    <div class="form-group">
      <%= f.label :name, '*Name' %>
      <%= f.text_field :name ,class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :description, '*Description' %>
      <%= f.text_field :description ,class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :price, '*Price' %>
      <%= f.text_field :price ,class: 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :image, 'image' %>
      <%= f.file_field :image %>
    </div>
  <%= f.button :submit, "CREATE PRODUCT", :class => 'btn' %>
<% end %>

<%= simple_form_for @product do |f| %>が元々のコードですが、これだとproducts_pathにリクエストを送ることになってしまします。namespaceの場合は、<%= simple_form_for [:admins,@product] do |f| %>このようにするとadmins_products_pathにリクエストを送れます。

"CREATE PRODUCT"ボタンを押すと、無事商品が登録されました。

Adminアカウントがログインしないと使えないようにする

ログインしないと商品を登録できないようにするために、下記のようにします。

class Admins::ApplicationController < ApplicationController
    before_action :authenticate_admin!
end

before_action :authenticate_user!と同じですね。これのadminバージョンです。

ログイン直後とログアウト直後のページを指定する

現状、ログイン直後は全てproducts#indexになってしまっているので、下記のようにApplicationControllerを変更します。

class ApplicationController < ActionController::Base
 def after_sign_in_path_for(resource)
    if resource.is_a?(Admin)
      admins_root_path
    else
      root_path
    end
end

def after_sign_out_path_for(resource)
    if resource == :admin
      new_admin_session_path
    else
      new_user_session_path
    end
  end
end

resource.is_a?(Admin)というのはresourceAdmin のインスタンスであれば true を返すという処理です。要するに、 resourceDevise に定義されているアカウントのクラスのインスタンスを意味します。

Adminでログインすると/adminsに無事リダイレクトされました!

まとめ【いせ日記】

今日で無事Adminアカウントを追加することができました😭

今日の勉強時間:朝1時間 夜4時間

今日も4時間学習することができました!

ブログ書くのがまだ慣れていないので、まだまだブログに時間がかかってしまいます。。

明日はAdminアカウントで売上を見れるようにしていきます!!

-LIFE

Copyright © Iseblog ,@2020 All Rights Reserved.