Module: Egregious
- Defined in:
- lib/egregious.rb,
lib/egregious/version.rb,
lib/egregious/extensions/exception.rb
Defined Under Namespace
Classes: Error
Constant Summary collapse
- VERSION =
"0.2.13"- @@exception_codes =
self._load_exception_codes
- @@root =
defined?(Rails) ? Rails.root : nil
Class Method Summary collapse
-
._load_exception_codes ⇒ Object
internal method that loads the exception codes.
-
.clean_class_name(str) ⇒ Object
Must sub out (Experimental) to avoid a class name: VariantAlsoNegotiates(Experimental).
-
.exception_codes ⇒ Object
this method exposes the @@exception_codes class variable allowing someone to re-configure the mapping.
-
.exception_codes=(exception_codes) ⇒ Object
this method exposes the @@exception_codes class variable allowing someone to re-configure the mapping.
- .included(base) ⇒ Object
-
.root ⇒ Object
exposes the root of the app.
-
.root=(root) ⇒ Object
set the root directory and stack traces will be cleaned up.
- .status_code(status) ⇒ Object
- .status_code_for_exception(exception) ⇒ Object
Instance Method Summary collapse
- #build_html_file_path(status) ⇒ Object
-
#clean_backtrace(exception) ⇒ Object
a little helper to help us clean up the backtrace if root is defined it removes that, for rails it takes care of that.
-
#egregious_exception_handler(exception) ⇒ Object
this is the method that handles all the exceptions we have mapped.
-
#egregious_flash(exception) ⇒ Object
override this if you want your flash to behave differently.
-
#egregious_log(exception) ⇒ Object
override this if you want your logging to behave differently.
-
#egregious_respond_to(exception) ⇒ Object
override this if you want to change your respond_to behavior.
-
#exception_codes ⇒ Object
this method will auto load the exception codes if they are not set by an external configuration call to self.exception_code already it is called by the status_code_for_exception method.
-
#notify_airbrake(exception) ⇒ Object
override this if you want to control what gets sent to airbrake.
- #status_code(status) ⇒ Object
-
#status_code_for_exception(exception) ⇒ Object
this method will lookup the exception code for a given exception class if the exception is not in our map then see if the class responds to :http_status if not it will return 500.
Class Method Details
._load_exception_codes ⇒ Object
internal method that loads the exception codes
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/egregious.rb', line 42 def self._load_exception_codes # by default if there is not mapping they map to 500/internal server error exception_codes = { SecurityError=>status_code(:forbidden) } # all status codes have a exception class defined Rack::Utils::HTTP_STATUS_CODES.each do |key, value| exception_codes.merge!(eval("Egregious::#{Egregious.clean_class_name(value)}")=>value.downcase.gsub(/\s|-/, '_').to_sym) end if defined?(ActionController) exception_codes.merge!({ AbstractController::ActionNotFound=>status_code(:bad_request), ActionController::InvalidAuthenticityToken=>status_code(:bad_request), ActionController::MethodNotAllowed=>status_code(:not_allowed), ActionController::MissingFile=>status_code(:not_found), ActionController::RoutingError=>status_code(:bad_request), ActionController::UnknownController=>status_code(:bad_request), ActionController::UnknownHttpMethod=>status_code(:not_allowed) #ActionController::MissingTemplate=>status_code(:not_found) }) end if defined?(ActiveModel) exception_codes.merge!({ ActiveModel::MissingAttributeError=>status_code(:bad_request)}) end if defined?(ActiveRecord) exception_codes.merge!({ ActiveRecord::AttributeAssignmentError=>status_code(:bad_request), ActiveRecord::MultiparameterAssignmentErrors=>status_code(:bad_request), ActiveRecord::ReadOnlyAssociation=>status_code(:forbidden), ActiveRecord::ReadOnlyRecord=>status_code(:forbidden), ActiveRecord::RecordInvalid=>status_code(:bad_request), ActiveRecord::RecordNotFound=>status_code(:not_found), ActiveRecord::UnknownAttributeError=>status_code(:bad_request) }) begin exception_codes.merge!({ ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded=>status_code(:bad_request) }) rescue => e # Unknown if using Rails 4 end end if defined?(Mongoid) require 'egregious/extensions/mongoid' exception_codes.merge!({ Mongoid::Errors::InvalidFind=>status_code(:bad_request), Mongoid::Errors::DocumentNotFound=>status_code(:not_found), Mongoid::Errors::Validations=>status_code(:unprocessable_entity) }) if defined?(Mongoid::VERSION) && Mongoid::VERSION > '3' exception_codes.merge!({ Mongoid::Errors::ReadonlyAttribute=>status_code(:forbidden), Mongoid::Errors::UnknownAttribute=>status_code(:bad_request) }) end end if defined?(Warden) exception_codes.merge!({ Warden::NotAuthenticated=>status_code(:unauthorized), }) end if defined?(CanCan) # technically this should be forbidden, but for some reason cancan returns AccessDenied when you are not logged in exception_codes.merge!({CanCan::AccessDenied=>status_code(:unauthorized)}) exception_codes.merge!({CanCan::AuthorizationNotPerformed => status_code(:unauthorized)}) end @@exception_codes = exception_codes end |
.clean_class_name(str) ⇒ Object
Must sub out (Experimental) to avoid a class name: VariantAlsoNegotiates(Experimental)
17 18 19 |
# File 'lib/egregious.rb', line 17 def self.clean_class_name(str) str.gsub(/\s|-|'/,'').sub('(Experimental)','') end |
.exception_codes ⇒ Object
this method exposes the @@exception_codes class variable allowing someone to re-configure the mapping. For example in a rails initializer: Egregious.exception_codes = => “503” or If you want the default mapping and then want to modify it you should call the following: Egregious.exception_codes.merge!(MyCustomException=>“500”)
154 155 156 |
# File 'lib/egregious.rb', line 154 def self.exception_codes @@exception_codes end |
.exception_codes=(exception_codes) ⇒ Object
this method exposes the @@exception_codes class variable allowing someone to re-configure the mapping. For example in a rails initializer: Egregious.exception_codes = => “503” or If you want the default mapping and then want to modify it you should call the following: Egregious.exception_codes.merge!(MyCustomException=>“500”)
163 164 165 |
# File 'lib/egregious.rb', line 163 def self.exception_codes=(exception_codes) @@exception_codes=exception_codes end |
.included(base) ⇒ Object
245 246 247 248 249 |
# File 'lib/egregious.rb', line 245 def self.included(base) base.class_eval do rescue_from 'Exception' , :with => :egregious_exception_handler end end |
.root ⇒ Object
exposes the root of the app
126 127 128 |
# File 'lib/egregious.rb', line 126 def self.root @@root end |
.root=(root) ⇒ Object
set the root directory and stack traces will be cleaned up
131 132 133 |
# File 'lib/egregious.rb', line 131 def self.root=(root) @@root=root end |
.status_code(status) ⇒ Object
27 28 29 30 31 32 33 34 |
# File 'lib/egregious.rb', line 27 def self.status_code(status) if status.is_a?(Symbol) key = status.to_s.split("_").map {|e| e.capitalize}.join(" ") Rack::Utils::HTTP_STATUS_CODES.invert[key] || 500 else status.to_i end end |
.status_code_for_exception(exception) ⇒ Object
181 182 183 184 |
# File 'lib/egregious.rb', line 181 def self.status_code_for_exception(exception) status_code(self.exception_codes[exception.class] || (exception.respond_to?(:http_status) ? (exception.http_status||:internal_server_error) : :internal_server_error)) end |
Instance Method Details
#build_html_file_path(status) ⇒ Object
241 242 243 |
# File 'lib/egregious.rb', line 241 def build_html_file_path(status) File.join(Rails.root, 'public', "#{status_code(status)}.html") end |
#clean_backtrace(exception) ⇒ Object
a little helper to help us clean up the backtrace if root is defined it removes that, for rails it takes care of that
137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/egregious.rb', line 137 def clean_backtrace(exception) if backtrace = exception.backtrace if Egregious.root backtrace.map { |line| line.sub Egregious.root.to_s, '' } else backtrace end end end |
#egregious_exception_handler(exception) ⇒ Object
this is the method that handles all the exceptions we have mapped
187 188 189 190 191 |
# File 'lib/egregious.rb', line 187 def egregious_exception_handler(exception) egregious_flash(exception) egregious_log(exception) egregious_respond_to(exception) end |
#egregious_flash(exception) ⇒ Object
override this if you want your flash to behave differently
194 195 196 |
# File 'lib/egregious.rb', line 194 def egregious_flash(exception) flash.now[:alert] = exception. end |
#egregious_log(exception) ⇒ Object
override this if you want your logging to behave differently
199 200 201 202 203 204 205 |
# File 'lib/egregious.rb', line 199 def egregious_log(exception) logger.fatal( "\n\n" + exception.class.to_s + ' (' + exception..to_s + '):\n ' + clean_backtrace(exception).join("\n ") + "\n\n") notify_airbrake(exception) end |
#egregious_respond_to(exception) ⇒ Object
override this if you want to change your respond_to behavior
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/egregious.rb', line 222 def egregious_respond_to(exception) respond_to do |format| status = status_code_for_exception(exception) format.xml { render :xml=> exception.to_xml, :status => status } format.json { render :json=> exception.to_json, :status => status } # render the html page for the status we are returning it exists...if not then render the 500.html page. format.html { # render the rails exception page if we are local/debugging if(Rails.application.config.consider_all_requests_local || request.local?) raise exception else render :file => File.exists?(build_html_file_path(status)) ? build_html_file_path(status) : build_html_file_path('500'), :status => status end } end end |
#exception_codes ⇒ Object
this method will auto load the exception codes if they are not set by an external configuration call to self.exception_code already it is called by the status_code_for_exception method
170 171 172 |
# File 'lib/egregious.rb', line 170 def exception_codes return Egregious.exception_codes end |
#notify_airbrake(exception) ⇒ Object
override this if you want to control what gets sent to airbrake
208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/egregious.rb', line 208 def notify_airbrake(exception) # tested with airbrake 4.3.5 and 5.0.5 if defined?(Airbrake) if(Airbrake.respond_to?(:notify_or_ignore)) env['airbrake.error_id'] = Airbrake.notify_or_ignore(exception, airbrake_request_data) # V4 else # V5 notice = Airbrake::Rack::NoticeBuilder.new(env).build_notice(exception) env['airbrake.error_id'] = Airbrake.notify(notice) end end end |
#status_code(status) ⇒ Object
36 37 38 |
# File 'lib/egregious.rb', line 36 def status_code(status) Egregious.status_code(status) end |
#status_code_for_exception(exception) ⇒ Object
this method will lookup the exception code for a given exception class if the exception is not in our map then see if the class responds to :http_status if not it will return 500
177 178 179 |
# File 'lib/egregious.rb', line 177 def status_code_for_exception(exception) Egregious.status_code_for_exception(exception) end |