たぬきエンジニア日記

神奈川の自社開発企業にてエンジニアをしているたぬきの日記。現在エンジニア歴は1年ほど。学習の発信を気ままにしている日記です。

【初心者向け】管理者ユーザーと管理者用controllerの追加方法[Ruby, Rails]

はじめに

どうもこんにちは、エンジニアとして就職を目指しているタヌキです。 2回連続でエンジニア(勉強中)っぽいことを書かなかったので、今回は勉強のお話をします。

今、個人でこんな感じのすごろくアプリを作っています。

Image from Gyazo

武蔵新城(JR南武線)周辺で「地域をもっと面白くしよう!」という人たちの集まりで作った、こんなすごろく(紙版:こちらも途中のものです。すみません。マス目の中にレストランを書き込んで、出た目のレストランに行って美味しいご飯を食べるという作りになっています)を(勝手に)アプリにしてみました。

すごろくの画像

ただし、地域のお店の情報を勝手にすごろくやアプリに登録してしまうといけないようなので、レストラン情報の登録(編集・削除も)は管理者のみが行えるようにしたいと思います。

そこで、管理者機能を実装することにしました。

すごーく初心者向けに書いていますので「そんなの知っているよ!」という人はどうぞ読み飛ばしてくださいね。

Userに管理者(admin)を追加する

まず、usersテーブルにadminというカラムをboolean型で追加して、デフォルトを0とします。

#コンソール
 rails g migration AddAdminToUsers
#migrationファイル
class AddAdminToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :admin, :boolean, default: false
  end
end

migrationファイルを編集したら、

rake db:migrate

を実施します。

次に、管理者権限をもつユーザーをseedファイルで追加します。

# seeds.rb

User.create!(username:  "管理者",
             email: "admin@example.jp",
             password:  "11111111",
             password_confirmation: "11111111",
             admin: true)

作成したら、

rake db:seed

で管理権限のあるuser情報をusersテープルに追加します。

この辺りの手順は、こちらのRailsチュートリアルの記述が詳しくて分かり易かったです。

このように管理者を追加することで、

current_user.admin?

などのメソッドが使えるようになります。

管理権限のあるユーザーとしてログインした場合にのみ特定のボタンを表示させる、 程度のシンプルな処理で良い場合には、こちらで実装は終わりとなります。

(セキュリティ上いろいろ配慮したい場合には、Railsチュートリアルをご覧ください)

一般ユーザーと管理ユーザー用のcontrollerを分ける

扱いたい機能が多岐にわたる場合には、管理ユーザー用のcontrollerと一般ユーザーのそれとを分けた方が便利だと思います。私も、今回は以下の方法でcontrollerを分けました。

app/controllers/admin 下に新たにcontrollerを作成する。

今回は、app/controllers 内に新たに admin というディレクトリを作成し、そこに、一般ユーザー用のものとは別に、restaurants_controller を作成したいと思います。

# ターミナル
rails g controller admin::restaurants

これで、一般ユーザー用と、管理ユーザー用の二つのrestaurants_controller.rbができました。 この時のディレクトリ構造はこんな感じです。

gyazo.com

この時、プログラムはディレクトリ構造からは /admin/restaurants_controller.rb の位置を探し当てることができません。

そのため、/admin/restaurants_controller.rb 内には下記のように「Admin::RestaurantsController」の「名前空間」を利用して、現在のディレクトリ構造を明記します。

class Admin::RestaurantsController < ApplicationController
 
  #中略

end

ついでに、管理ユーザー以外で特定のアクションを実行しようとした場合には、トップページにリダイレクトさせる、 if_not_adminメソッドも作成し、before_actionで設定しました。

class Admin::RestaurantsController < ApplicationController
  before_action :if_not_admin

  #中略

  private
  def if_not_admin
    redirect_to root_path unless current_user.admin?
  end
end

最後に、edit, show, destroy などのアクションで使用する変数をセットします。

class Admin::RestaurantsController < ApplicationController
  before_action :if_not_admin
  before_action :set_restaurant, only: [:show, :edit, :destroy]

 # 中略

  private
  def if_not_admin
    redirect_to root_path unless current_user.admin?
  end

  def set_restaurant
    @restaurant = Restaurant.find(params[:id])
  end
end

そのほかのアクションに必要な設定は別途していると思ってください。

routingの設定

この時のルーティングは下記ように設定しています。 restaurants#indexやrestaurants#show が二つあることになりますが、それぞれ、管理ユーザー(admin)用と、一般ユーザー用とに分けることができました。

# routes.rb

resources :restaurants, only: [:index, :show] 
  namespace :admin do
    resources :restaurants, only: [:index, :new, :create, :show,  :edit, :destroy]
  end
end

rake routesの結果も下記の通り。

Image from Gyazo

管理者用のページは /admin/restaurants (indexアクション) など /admin ディレクトリ下に配置することができています。 これで、管理者用ページと、一般ユーザー用ページが分かれて全体的にわかりやすいサイトの構造になりました^^

Gemについて

なお、管理者画面なども作りたい場合には、

rails_admin」(管理画面を生成するGem) 「cancancan」(管理者権限を設定するGem)

などがあるようです。 こちらも機会があれば調べてみたいです。

それでは、ここまで読んでくださりありがとうございました^^ 次回は、form_withでselect boxを実装した時の設定が色々勉強になったので、それについて投稿してみたいと思います。

6/13追記:

6/11投稿時点では、edit, showなどの一部アクションが表示できないエラーが発生しておりましたが、その後無事解決しました。(単純な記述ミスでした。トホホ・・・)