はじめに
ポートフォリオで、コントローラーのリファクタリングをやったので、備忘録として記事を書きます。
#環境
・Ruby 2.6.3
・Ruby on Rails 5.2.5
リファクタリング1つ目 concemsを使う
共通記述を複数のコントローラーで使う時にやる
app/controllers/concernsにファイルを追加し、必要箇所で読み込ませる
controllers/concerns/search.rb
module Search
extend ActiveSupport::Concern
def search
@keyword = params[:word]
redirect_to request.referer, notice: "検索文字を入れて下さい" if @keyword.blank?
searcher = Searcher.new(params[:word].split(/[[:blank:]]+/))
@users = Kaminari.paginate_array(searcher.users).page(params[:page]).per(12)
@groups = Kaminari.paginate_array(searcher.groups).page(params[:page]).per(12)
@posts = Kaminari.paginate_array(searcher.posts).page(params[:page]).per(12)
end
end
controllers/user/searches_controller.rb
class User::SearchesController < ApplicationController
include Search
before_action :search
end
controllers/admin/searches_controller.rb
class Admin::SearchesController < ApplicationController
include Search
before_action :search
end
これで同じ記述の箇所はスッキリ〜〜
リファクタリング2つ目 application_controller.rbにかいて継承
複数のコントローラに同じ処理が記述されている場合(継承)に役立つ
controllers/user/●●●●●_controller.rb
class ●●●●●Controller < ApplicationController
before_action :authorize_owner
private
def authorize_owner
redirect_to root_path unless current_user.owner?
end
end
authorize_ownerメソッドが定義されていて、このメソッドを複数のコントローラーで使うよ!って時に
application_controller.rbに記載して継承すれば、記述量少なくなります。
※今回はauthorize_ownerメソッド使ってるけど、例として使っているのでどんなメソッドでもいい
controllers/user/application_controller.rb
class ApplicationController < ApplicationController
private
def authorize_owner
redirect_to root_path unless current_user.owner?
end
end
↓継承したいコントローラーに。
controllers/user/●●●●●_controller.rb
class ●●●●●Controller < ApplicationController
before_action :authorize_owner
end
リファクタリング3つ目 callbackを利用して共通化
定義したメソッドをbefore_actionなどで共通化させちゃう方法
複数のアクションに同じ処理が記述されている場合に役立つ
controllers/user/●●●●●_controller.rb
class User::PostsController < ApplicationController
before_action :set_group, only: %i[new index show create update destroy]
before_action :set_post, only: %i[show update destroy]
def new
@post = Post.new
end
def index
@posts = @group.posts.includes(:user).order(updated_at: :desc).page(params[:page]).per(12)
end
def show
@comment = Comment.new
respond_to do |format|
format.html do
end
format.csv do
send_data render_to_string, filename: "投稿詳細.csv", type: :csv
end
end
end
一部アクション割愛
private
#ここで記述が重なるコードをメソッド化
def set_group
@group = Group.find(params[:group_id])
end
def set_post
@post = Post.find(params[:id])
end
#ここまで
#これをbefore_actionで呼び出しちゃえばおk
end
リファクタリング4つ目 王道モデルにメソッド定義
長ったらしいコードをモデルに定義してコントローラーをすっきりしようよ作戦
controllers/user/homes_controller.rb
class User::HomesController < ApplicationController
def top
@group_ranks = Group.find(GroupUser.group(:group_id).order("count(group_id) desc").limit(6).pluck(:group_id))
@admins = Admin.first(6)
end
end
#この部分をメソッド化してスッキリさせる#
Group.find(GroupUser.group(:group_id).order("count(group_id) desc").limit(6).pluck(:group_id))
モデルに定義
models/group.rb
# ランキング用メソッド
def self.all_group_ranks
find(GroupUser.group(:group_id).order("count(group_id) desc").limit(6).pluck(:group_id))
end
コントローラーに呼び出す
controllers/user/homes_controller.rb
class User::HomesController < ApplicationController
def top
@group_ranks = Group.all_group_ranks # Group.rbでメソッド定義
@admins = Admin.first(6)
end
end
###以上自分が実際にやったリファクタリングでした〜〜