rails concernの使い方

初めに

rails の concernについてちょっとまとめたもの

concernとは

concernとはrailsの共通部分をまとめるみたいな使い方が一般的なようで、例えばuserモデルでもpostモデルでも使うスコープなりメソッドがあった場合にまとめることができます。

以下は今日と機能に作成されたデータを得るスコープです。

scope :today, -> {where(created_at: 0.day.ago.all_day)}
scope :yesterday, -> {where(created_at: 1.day.ago.all_day)}

scope :today, -> {where(created_at: 0.day.ago.all_day)}
scope :yesterday, -> {where(created_at: 1.day.ago.all_day)}

みたいな感じで書いているとしてこれはおんなじスコープを書いているのでまとめたい!というときにconcernを使います。

concernsフォルダがmodels以下にあると思うのでその中にday.rbというファイルを作成します。

そしてその中に

module Day
  extend ActiveSupport::Concern

  included do
  scope :today, -> {where(created_at: 0.day.ago.all_day)}
  scope :yesterday, -> {where(created_at: 1.day.ago.all_day)}
  end
end

moduleの名前はファイルの名前と同じにする必要があります。

そしてuser.rb,post.rbに

include Day

include Day

と書いたら使えるようになります。

#ほかの使い方

自分でアプリを作っていて複数のモデルでおんなじスコープを使いたいとかあんまりないのですがモデルのファイルやapplication_controller.rbの中身が多くなりすぎて見づらくなるということが結構ありました。

なので見やすくするためにある程度処理をまとめてconcernの中に入れています。

例えばapplication_controller.rbのエラーハンドルを書いていた場合

    class Forbidden < ActionController::ActionControllerError; end
    class IpAddressRejected < ActionController::ActionControllerError; end    
    rescue_from Exception, with: :rescue500
    rescue_from ActiveRecord::RecordNotFound, with: :not_found
    rescue_from Forbidden, with: :rescue403
    rescue_from IpAddressRejected, with: :rescue403
    rescue_from ActionController::RoutingError, with: :rescue404

    def rescue500(e)
        @exception = e 
        render 'error_messages/500'
    end 

    def rescue403(e)
        @exception = e 
        render 'error_messages/403' 
    end 


    def not_found(e)
        @exception = e
        render 'error_messages/404'
    end 

    def rescue404(e)
        @exception = e 
        render 'error_messages/404'
    end 


みたいなのがapplication_controller.rbに書かれています。

正直これだとapplication_controllerが見づらいです。

なので

controllers/concernsに

error_handle.rbというファイルを作り

その中に

module ErrorHandle
extend ActiveSupport::Concern

included do 
    class Forbidden < ActionController::ActionControllerError; end 
    class IpAddressRejected < ActionController::ActionControllerError; end 

    rescue_from Exception, with: :rescue500
    rescue_from ActiveRecord::RecordNotFound, with: :not_found
    rescue_from Forbidden, with: :rescue403
    rescue_from IpAddressRejected, with: :rescue403
    rescue_from ActionController::RoutingError, with: :rescue404

    def rescue500(e)
        @exception = e 
        render 'error_messages/500'
    end 

    def rescue403(e)
        @exception = e 
        render 'error_messages/403' 
    end 


    def not_found(e)
        @exception = e
        render 'error_messages/404'
    end 

    def rescue404(e)
        @exception = e 
        render 'error_messages/404'
    end 
end 

とかいてapplication_controller.rbでincludeしてあげれば中身は

ruby
class ApplicationController < ActionController::Base
include ErrorHandle
end

みたいにすっきりします。

自分の場合は配列とその中身をfreezeさせるメソッドfreeze_allを作ってそれを使うことがあるのですがそういうのは

concernsにsome_methods.rbというファイルをつくって


module SomeMethods
extend ActiveSupport::Concern

def freeze_all
    self.each do |item|
        item.freeze 
    end 
    self.freeze
end

みたいに使うメソッドもまとめてます。

こういったやり方がありなのか知らないけど…

おわり

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です