Railsでconcernsを使えば、application_controller.rbを汚さずに共通化できる
通常?今までRailsでapplication_controller.rbに共通化した処理を書いていたが、
エラー処理を書いてあるのでできればそちらを使わずに共通化をしたい。ということで、concernsを使ってリファクタリングする。
そもそもconcernsで共通化するのでスタンダード?かも。
お題としては、
- トップページには最新の記事を5件だけ表示したい。(about等複数ページ)
- 記事一覧ページでは最新の記事を20件表示したい。
- 記事は@latest_entries
というインスタンス変数でViewに渡したい。
こちらをリファクタリングしていく様子を記述する。
通常の無駄な記述 (リファクタリング前)
home_controller.rb
class HomeController < ApplicationController def index @latest_articles = Article.limit(5).order("created_at DESC") end end
articles_controller.rb
class ArticleController < ApplicationController def index @latest_articles = Article.limit(20).order("created_at DESC") end end
DRYの哲学があるので、共通化をする。
application_controller.rbでリファクタリング(今まで)
application_controller.rb
class ApplicationController < ApplicationController def error_hogehoge end def error_fugafuga end def latest_articles(num) @latest_articles = Article.limit(num).order("created_at DESC") end end
error_hogehoge
はエラー処理のメソッドとして、サンプルとして記述してある。
home_controller.rb
class HomeController < ApplicationController before_action -> { latest_articles(5) }, only: [:index] def index end end
articles_controller.rb
class ArticleController < ApplicationController before_action -> { latest_articles(20) }, only: [:index] def index end end
こんな感じで共通化していく。 が、application_controller.rbはエラー処理の記述があって、できれば汚したくない! という場合にconcernsを使って共通化もできる。
concernsでリファクタリング
latest_articles.rb
module LatestArticles extend ActiveSupport::Concern def latest_articles(num) @latest_articles = Article.limit(num).order("created_at DESC") end end
application_controller.rb
class ApplicationController < ApplicationController def error_hogehoge end def error_fugafuga end end
ここには何も書かなくても、大丈夫。
home_controller.rb
class HomeController < ApplicationController include LatestArticles before_action -> { latest_articles(5) }, only: [:index] def index end end
articles_controller.rb
class ArticleController < ApplicationController include LatestArticles before_action -> { latest_articles(20) }, only: [:index] def index end end
concernsの方にクラスとかメソッドを記述して、
controllerの方で、include クラス名
を記述してあげれば利用できる。
これだけだとあまり有り難みがないかもしれないが、
application_controller.rb
に記述しなくても、
concerns
で共通化ができる。
使いようによってはもっと複雑なこともできる。はず。