<commit_before>module ExceptionHandler
  class ExceptionController < ActionController::Base

    #Response
    respond_to :html, :xml, :json

  	#Dependencies
  	before_action :status, :app_name

    #Layout
    layout :layout_status

    ####################
    #      Action      #
    ####################

  	#Show
    def show
      handled = run_exception_callback
      return if handled

      customize_response 

      respond_to do |format|
        format.any(:html, :json, :xml) { render status: @status }
      end
    end

    ####################
    #   Dependencies   #
    ####################

    protected

    #Info
    def status
      @exception  = env['action_dispatch.exception']
      @status     = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
      @response   = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
    end

    #Format
    def details
      @details ||= {}.tap do |h|
        I18n.with_options scope: [:exception, :show, @response], exception_name: @exception.class.name, exception_message: @exception.message do |i18n|
          h[:name]    = i18n.t "#{@exception.class.name.underscore}.title", default: i18n.t(:title, default: @exception.class.name)
          h[:message] = i18n.t "#{@exception.class.name.underscore}.description", default: i18n.t(:description, default: @exception.message)
        end
      end
    end
    helper_method :details

    # Response configuration
    # ----------------------
    # Allows additional configuration of the response
    # Right now this is status-specific, but could be extended to provide 
    # exception-specific customizations
    #
    # For example this could be used to turn a 500 Internal Server error into a temporary 503 error,
    # and add a Retry-After header, which is better for SEO if you expect errors to be fixed quickly
    # See: https://yoast.com/http-503-site-maintenance-seo/
    def customize_response
      cbs = ExceptionHandler.config.customize_response_by_status
      # could also add support for customizations by exception type

      if (cbs.kind_of? Hash) && (cbs[@status].kind_of? Hash)
        customize_response_with(cbs[@status])
      end
    end

    def customize_response_with(customizations)
      @status = customizations[:status] if customizations[:status] != nil
      response.headers.merge!(customizations[:headers]) if (customizations[:headers].kind_of? Hash)
      # could support more customizations here (e.g. layout, view, action, etc.)
    end


    # Run the callback function, if set
    def run_exception_callback
      handled = false
      ecb=ExceptionHandler.config.callback
      
      if (ecb.kind_of? Hash) && (ecb[:class] != nil)
        cb_response = ecb[:class].send(
          (ecb[:method] || :'exception_handler_callback'), {
            :env => env,
            :exception => @exception,
            :status => @status,
            :response => @response,
            :details => details
          }
        )
        handled = true if cb_response == true
      end

      return handled
    end

    ####################
    #      Layout      #
    ####################

    private

    #Layout
    def layout_status
      return ExceptionHandler.config.exception_layout || 'error' if @status.to_s != "404"
      ExceptionHandler.config.error_layout || 'application'
    end

    #App
    def app_name
      @app_name = Rails.application.class.parent_name<commit_msg>Allow callback handler to be specified as a string rather than a class to avoid triggering autoloading in initializers<commit_after>module ExceptionHandler
  class ExceptionController < ActionController::Base

    #Response
    respond_to :html, :xml, :json

  	#Dependencies
  	before_action :status, :app_name

    #Layout
    layout :layout_status

    ####################
    #      Action      #
    ####################

  	#Show
    def show
      handled = run_exception_callback
      return if handled

      customize_response 

      respond_to do |format|
        format.any(:html, :json, :xml) { render status: @status }
      end
    end

    ####################
    #   Dependencies   #
    ####################

    protected

    #Info
    def status
      @exception  = env['action_dispatch.exception']
      @status     = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
      @response   = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
    end

    #Format
    def details
      @details ||= {}.tap do |h|
        I18n.with_options scope: [:exception, :show, @response], exception_name: @exception.class.name, exception_message: @exception.message do |i18n|
          h[:name]    = i18n.t "#{@exception.class.name.underscore}.title", default: i18n.t(:title, default: @exception.class.name)
          h[:message] = i18n.t "#{@exception.class.name.underscore}.description", default: i18n.t(:description, default: @exception.message)
        end
      end
    end
    helper_method :details

    # Response configuration
    # ----------------------
    # Allows additional configuration of the response
    # Right now this is status-specific, but could be extended to provide 
    # exception-specific customizations
    #
    # For example this could be used to turn a 500 Internal Server error into a temporary 503 error,
    # and add a Retry-After header, which is better for SEO if you expect errors to be fixed quickly
    # See: https://yoast.com/http-503-site-maintenance-seo/
    def customize_response
      cbs = ExceptionHandler.config.customize_response_by_status
      # could also add support for customizations by exception type

      if (cbs.kind_of? Hash) && (cbs[@status].kind_of? Hash)
        customize_response_with(cbs[@status])
      end
    end

    def customize_response_with(customizations)
      @status = customizations[:status] if customizations[:status] != nil
      response.headers.merge!(customizations[:headers]) if (customizations[:headers].kind_of? Hash)
      # could support more customizations here (e.g. layout, view, action, etc.)
    end


    # Run the callback function, if set
    def run_exception_callback
      handled = false
      ecb=ExceptionHandler.config.callback
      
      if (ecb.kind_of? Hash) && (ecb[:class] != nil)
        ecb[:class] = ecb[:class].constantize if ecb[:class].kind_of? String
        cb_response = ecb[:class].send(
          (ecb[:method] || :'exception_handler_callback'), {
            :env => env,
            :exception => @exception,
            :status => @status,
            :response => @response,
            :details => details
          }
        )
        handled = true if cb_response == true
      end

      return handled
    end

    ####################
    #      Layout      #
    ####################

    private

    #Layout
    def layout_status
      return ExceptionHandler.config.exception_layout || 'error' if @status.to_s != "404"
      ExceptionHandler.config.error_layout || 'application'
    end

    #App
    def app_name
      @app_name = Rails.application.class.parent_name
{'fraction_non_alphanumeric': 0.13218390804597702, 'fraction_numerical': 0.00672834314550042, 'mean_word_length': 2.691153647180548, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5009069', 'n_tokens_mistral': 2040, 'n_tokens_neox': 1936, 'n_words': 518}