掲示板/ユーザのCRUD機能の作成(管理者画面)

どうもどハマりエンジニアです。

 

本日は前回の引き続きで、管理者画面の掲示板及びユーザーのCRUD機能を作成していきます。

 

ユーザーと掲示板のコントローラー作成

$rails g controller admin::users

$rails g controller admin::boards

コントローラーは普通のCRUD機能ですので、一般での時と同じように作成します。

admin/user_controller.rb

class Admin::UsersController < Admin::BaseController
before_action :set_user, only: %i[show edit update destroy]
def index
@search = User.ransack(params[:q])
@user = @search.result(distinct: true).order(created_at: :desc).page(params[:page])
end

def show; end

def edit; end

def update
if @user.update(user_params)
redirect_to admin_user_path(@user), success: 'ユーザーを更新しました'
else
flash.now[:danger] = '更新できませんでした'
render 'edit'
end
end

def destroy
@user.destroy!
redirect_to admin_users_path, success: 'ユーザーを削除しました'
end

private

def set_user
@user = User.find(params[:id])
end

def user_params
params.require(:user).permit(:email, :first_name, :last_name, :abatar)
end
end

 

admin/boards_controller.rb

class Admin::BoardsController < Admin::BaseController
before_action :set_board, only: %i[show edit update destroy]
def index
@search = Board.ransack(params[:q])
@board = @search.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page])
end

def show; end

def edit; end

def update
if @board.update(board_params)
redirect_to admin_board_path(@board), success: '掲示板を更新しました'
else
flash.now[:danger] = '更新できませんでした'
render 'edit'
end
end

def destroy
@board.destroy!
redirect_to admin_boards_path, success: '掲示板を削除しました'
end

private

def set_board
@board = Board.find(params[:id])
end

def board_params
params.require(:board).permit(:title, :body, :board_image, :board_image_cache)
end
end

 

ルーティングの設定

routes.rb

namespace :admin do
root 'dashboards#index', as: :root
get 'login', to: 'user_sessions#new'
post 'login', to: 'user_sessions#create'
delete 'logout', to: 'user_sessions#destroy'
resources :users, only: %i[index show edit update destroy] 追加
resources :boards, only: %i[index show edit update destroy] 追加
end

 

ビューの作成及び検索機能(日付)の設定等

まず、ユーザー一覧に管理者で検索できるようにしていきます。

 

admin/users/index.html.erb (検索部分のみ)

<%# 検索機能 %>
<%= search_form_for @search, url: admin_users_path do |f| %>
<div class="row">
<div class="form-inline align-items-center mx-auto">
<div class="col-auto">
<%= f.search_field :first_name_or_last_name_cont, class: 'form-control',
           placeholder: '検索ワード' %>
</div>
<div class="col-auto">
<%= f.select :role_eq, User.roles_i18n.invert.map
          { |key, value| [key, User.roles[value]] },
          { include_blank: '指定なし' }, { class: 'form-control' } %>
</div>
<div class="col-auto">
<%= f.submit value: '検索', class: 'btn btn-primary' %>
</div>
</div>
</div>
<% end %>

 

f.selectは、

<%= f.select 属性, 選択肢の集合, {オプション}, {HTMLオプション} %>

と書くか、あるいは、

<%= f.select( 属性, 選択肢の集合, {オプション}, {HTMLオプション} ) %>

と括弧を使って書きます。

 

オプションは、

{ include_blank: '指定なし' }

のようにします。この例では、何も選択されていない時は、 ‘指定なし’ という項目が選択されるという定義です。セレクトボックスの1番目の選択肢に’指定なし’ が追加されます。

 ransackを使うとboardsテーブルに対して:title_eqと記述するだけでSQLを内部で走らせてくれます。
上記のeqの部分をPredicateと呼び、Predicateを変更することで様々な条件のデータを検索することができます。

 

User.roles_i18n.invert.map i18nを使えば、選択部分を日本語に変えることができます。inverでkeyとvalueの関係を逆にして、mapで表示させる設定をしています。例えば、コンソールを開いて下記を実行します。そうするとkeyがgeneral、valueが一般になっています。なので表示させたいのは一般なので、invertを使い反転させます。あとは、mapをつかい、表示の設定をしてあげます。

irb(main):001:0> User.roles_i18n

=> {"general"=>"一般", "admin"=>"管理者"}

 

views/ja.yml

enums:
user:
role:
general: '一般'
admin: '管理者'

 

i18nでは上記のように記載してあげます。

以上で管理者権限での検索が可能になります。

<参考記事>

https://310nae.com/rails-selectbox/

 

 

次に掲示板一覧にて日付で検索をできるようにしていきます。

 

admin/boards.index.html.erb(検索機能のみ)

<%# 検索機能 %>
<%= search_form_for @search, url: admin_boards_path do |f| %>
<div class="row">
<div class="form-inline align-items-center mx-auto">
<div class="col-auto">
<%= f.search_field :title_or_body_cont, class: 'form-control',
placeholder: '検索ワード' %>
</div>
<div class="col-auto">
<%= f.date_field :created_at_gteq, class: 'form-control' %>
<span></span>
<%= f.date_field :created_at_lteq_end_of_day, class: 'form-control' %>
</div>
<div class="col-auto">
<%= f.submit value: '検索', class: 'btn btn-primary' %>
</div>
</div>
</div>
<% end %>

 

ransackで oooo/oo/oo から xxxx/xx/xx までというふうに日付検索ができるようにしていたのですが、そのままだと xxxx/xx/xx の部分の時間が00:00:00となってしまう事で、指定した日付の前日までのデータしか取得できませんでした。

日付の検索についてはいつからいつまでといった感じにするためにransackをカスタマイズする必要があります。そのためransack.rbというファイルを作り、そこに設定を加えていきます。ちなみにgteq(以上)、lteq(以下)というpredicate(述語)でransackをインストールすることで使えるものです。

 

config/initializers/ransack.rb

Ransack.configure do |config|
config.add_predicate 'lteq_end_of_day',
arel_predicate: 'lteq', # カスタマイズしたいpredicateを指定
formatter: proc { |v| v.end_of_day } # どのようにフォーマットするか指定
end

 

これできちんと指定した日付のデータも検索結果に含まれるようになりました!

SQLを確認してみてもきちんと 2019-03-01 00:00:00 から 2019-03-01 23:59:59.999999 までというようにデータを検索してくれております。

 

これで日付での検索機能は完了です!

 

掲示板のメニューをアクティブに

どいうことかというと、例えば掲示板一覧にいるときは、メニューのボタンの色をかえるということ。これは直接ビューに書き込んでもいいのですが、ヘルパーに書き込んだ方が便利なので、今回はヘルパー に記載していきます。

 

app/helpers/application_helper.rb

def active?(controller_name)
return 'active' if controller_name == params[:controller]
end

 

 

admin/shared/_sidebar.html.erb

<%= link_to admin_boards_path, class: "nav-link #{ active?("admin/boards") }" do %>

 

へるぱーで定義したメソッドをつかえば、これだけで掲示板メニューをアクティブにすることができます。

 

以上で、おおまかな掲示板/ユーザのCRUD機能の作成(管理者画面)の説明を終わります。