auto_error 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +20 -0
  4. data/app/assets/images/auto_error/spinner.gif +0 -0
  5. data/app/assets/javascripts/auto_error/app_errors/configure.coffee +21 -0
  6. data/app/assets/javascripts/auto_error/app_errors/index.coffee +13 -0
  7. data/app/assets/javascripts/auto_error/app_errors/model.coffee +6 -0
  8. data/app/assets/javascripts/auto_error/app_errors/views/app_errors.coffee +38 -0
  9. data/app/assets/javascripts/auto_error/app_errors/views/base.coffee +57 -0
  10. data/app/assets/javascripts/auto_error/application.js +8 -0
  11. data/app/assets/stylesheets/auto_error/app_errors.css.erb +45 -0
  12. data/app/assets/stylesheets/auto_error/application.css +5 -0
  13. data/app/assets/templates/auto_error/app_error.hbs +11 -0
  14. data/app/controllers/auto_error/app_errors_controller.rb +17 -0
  15. data/app/controllers/auto_error/application_controller.rb +13 -0
  16. data/app/controllers/auto_error/errors_controller.rb +32 -0
  17. data/app/controllers/auto_error/main_controller.rb +9 -0
  18. data/app/decorators/auto_error/app_error_decorator.rb +13 -0
  19. data/app/helpers/auto_error/application_helper.rb +12 -0
  20. data/app/models/auto_error/app_error.rb +64 -0
  21. data/app/views/auto_error/main/index.html.haml +32 -0
  22. data/app/views/errors/404.html.erb +1 -0
  23. data/app/views/errors/500.html.erb +1 -0
  24. data/app/views/layouts/auto_error/application.html.erb +11 -0
  25. data/app/views/layouts/errors.html.erb +1 -0
  26. data/config/initializers/fabrication.rb +6 -0
  27. data/config/routes.rb +4 -0
  28. data/db/migrate/20130128004546_create_auto_error_app_errors.rb +19 -0
  29. data/lib/auto_error.rb +43 -0
  30. data/lib/auto_error/auth_context.rb +18 -0
  31. data/lib/auto_error/config.rb +39 -0
  32. data/lib/auto_error/context_shorthand.rb +15 -0
  33. data/lib/auto_error/engine.rb +13 -0
  34. data/lib/auto_error/errors.rb +6 -0
  35. data/lib/auto_error/version.rb +3 -0
  36. data/lib/auto_error/view_context.rb +10 -0
  37. data/lib/core_ext/proc_ext.rb +23 -0
  38. data/lib/tasks/auto_error_tasks.rake +4 -0
  39. data/lib/templates/auto_error.rb +11 -0
  40. metadata +311 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Ryan Funduk
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ = AutoError
2
+
3
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AutoError'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ namespacedTemplates = ->
2
+ h = {}
3
+ for name, func of window.HandlebarsTemplates
4
+ if name.match( /\// )
5
+ nesting = h
6
+ parts = name.split('/')
7
+ while (part = parts.shift())
8
+ if parts.length == 0
9
+ nesting[part] = func
10
+ else
11
+ nesting[part] ||= {}
12
+ nesting = nesting[part]
13
+ else
14
+ h[name] = func
15
+ h
16
+
17
+ _.extend( window.App, {
18
+ mobile: navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i)
19
+ Templates: namespacedTemplates().auto_error
20
+ Views: {}
21
+ } )
@@ -0,0 +1,13 @@
1
+ #= require ./configure
2
+
3
+ #= require ./model
4
+ #= require ./views/base
5
+ #= require ./views/app_errors
6
+
7
+ $(document).ready ->
8
+ $.ajaxSetup
9
+ headers:
10
+ 'X-CSRF-Token': $("meta[name='csrf-token']").attr( 'content' )
11
+
12
+ App.rootAppErrorsPath = $('#app_errors').data('url')
13
+ new App.Views.AppErrors()
@@ -0,0 +1,6 @@
1
+ class App.AppError extends Backbone.Model
2
+
3
+ class App.AppErrors extends Backbone.Collection
4
+ model: App.AppError
5
+ name: 'app errors'
6
+ url: -> App.rootAppErrorsPath
@@ -0,0 +1,38 @@
1
+ class AppError extends App.Views.PolledItem
2
+ template: App.Templates.app_error
3
+ events:
4
+ 'click a.show_backtrace': 'toggleBacktrace'
5
+ 'click a.remove': 'destroy'
6
+ render: ->
7
+ json = @model.toJSON()
8
+ json.prettyData = []
9
+ for k, v of json.data
10
+ json.prettyData.push "#{k}: #{v}"
11
+ json.prettyData = json.prettyData.join("\n")
12
+ json.timestamp = moment(json.created_at).format( "YYYY-MM-DD[<br/>at] h:mma" )
13
+ @$el.html( @template( json ) )
14
+ return @
15
+ toggleBacktrace: ->
16
+ link = @$('a.show_backtrace')
17
+ bt = @$('.backtrace')
18
+ if bt.is(':visible')
19
+ bt.hide()
20
+ link.text('show backtrace...')
21
+ else
22
+ bt.html( @model.get('backtrace').replace( /\n/g, "<br/>" ) ).show()
23
+ link.text('hide backtrace...')
24
+ destroy: ->
25
+ @model.destroy()
26
+ @remove()
27
+
28
+ class AppErrorsList extends App.Views.PollingList
29
+
30
+ class App.Views.AppErrors extends Backbone.View
31
+ el: 'body'
32
+ initialize: ->
33
+ @errors = new AppErrorsList(
34
+ el: @$('#app_errors table')
35
+ reset: false
36
+ viewClass: AppError
37
+ collectionClass: App.AppErrors
38
+ )
@@ -0,0 +1,57 @@
1
+ class App.Views.PolledItem extends Backbone.View
2
+ tagName: 'tr'
3
+ initialize: ->
4
+ @model.on 'change', @render, @
5
+
6
+ class App.Views.PollingList extends Backbone.View
7
+ events:
8
+ 'click .poller a': 'togglePolling'
9
+ initialize: ->
10
+ @collection = new @options.collectionClass( [] )
11
+ @spinner = @$('tfoot .poller .spinner')
12
+ @polling = false
13
+ @body = @$('tbody')
14
+ @emptyMessage = @body.html().replace(/[\r\n]\s+/g, '')
15
+ @collection.on 'remove', @remove, @
16
+ @collection.on 'add', @render, @
17
+ @collection.fetch( update: true )
18
+ @views = {}
19
+ remove: ( m ) ->
20
+ @views[m.id] = null
21
+ @render()
22
+ render: ->
23
+ if @collection.isEmpty()
24
+ message = $(@emptyMessage)
25
+ message.find('p.loading_message').text( "No #{@collection.name}!" )
26
+ @body.html( message )
27
+ else
28
+ @body.find('p.loading_message').parents('tr').remove()
29
+ @collection.each (m) =>
30
+ return if @views[m.id]
31
+ v = new @options.viewClass( model: m )
32
+ @views[m.id] = v
33
+ @body.prepend v.render().el
34
+ @$('tfoot p.total strong').text( @collection.length )
35
+ togglePolling: (e) ->
36
+ link = $(e.target)
37
+ if @polling == false
38
+ @polling = true
39
+ @poll()
40
+ link.text( 'stop polling' )
41
+ else
42
+ @polling = false
43
+ link.text( 'start polling' )
44
+ @spinner.hide()
45
+ poll: ->
46
+ if @polling
47
+ startTime = new Date().getTime()
48
+ @spinner.fadeIn()
49
+ args =
50
+ update: true
51
+ success: =>
52
+ setTimeout( _.bind(@poll, @), 2000 ) if @polling
53
+ setTimeout(
54
+ _.bind( @spinner.fadeOut, @spinner )
55
+ Math.max( (new Date().getTime() - startTime), 500 )
56
+ )
57
+ @collection.fetch args
@@ -0,0 +1,8 @@
1
+ //= require jquery
2
+ //= require jquery_ujs
3
+ //= require auto_error/moment
4
+ //= require auto_error/underscore-1.4.4
5
+ //= require auto_error/backbone-0.9.10
6
+ //= require handlebars.runtime
7
+ //= require_tree ../../templates/auto_error
8
+ //= require ./app_errors
@@ -0,0 +1,45 @@
1
+ table.polling tr td p.loading_message {
2
+ font-size: 20px;
3
+ margin: 25px 0;
4
+ text-align: center;
5
+ }
6
+
7
+ table.polling tbody pre {
8
+ font-size: 13px;
9
+ line-height: 15px;
10
+ }
11
+ table.polling tbody a.button {
12
+ display: block;
13
+ margin-bottom: 4px;
14
+ }
15
+ table.polling tfoot p.total {
16
+ padding: 0;
17
+ margin: 0;
18
+ line-height: 24px;
19
+ margin-right: 5px;
20
+ font-weight: normal;
21
+ text-align: right;
22
+ }
23
+ table.polling tfoot .poller a {
24
+ float: left;
25
+ margin: 0;
26
+ padding-top: 6px;
27
+ }
28
+ table.polling tfoot .poller .spinner {
29
+ display: none;
30
+ float: left;
31
+ width: 24px;
32
+ height: 24px;
33
+ background: transparent url(<%= image_path('auto_error/spinner.gif') %>) no-repeat center center;
34
+ margin-left: 12px;
35
+ }
36
+
37
+ #app_errors table tbody .backtrace {
38
+ width: 530px;
39
+ height: 250px;
40
+ overflow: scroll;
41
+ font-family: monospace;
42
+ font-size: 13px;
43
+ line-height: 15px;
44
+ white-space: nowrap;
45
+ }
@@ -0,0 +1,5 @@
1
+ /*
2
+ *= require_self
3
+ *= require auto_error/foundation
4
+ *= require_tree .
5
+ */
@@ -0,0 +1,11 @@
1
+ <td>
2
+ <strong>{{message}}</strong>
3
+ <br/>
4
+ <a href="javascript:void(0);" class='show_backtrace'>show backtrace...</a>
5
+ <div class='backtrace' style='display: none;'></div>
6
+ </td>
7
+ <td><pre>{{{prettyData}}}</pre></td>
8
+ <td>{{{timestamp}}}</td>
9
+ <td>
10
+ <a href="javascript:void(0);" class='remove button radius tiny secondary'>resolved</a>
11
+ </td>
@@ -0,0 +1,17 @@
1
+ module AutoError
2
+ class AppErrorsController < ApplicationController
3
+ before_filter :ensure_authenticated
4
+
5
+ def index
6
+ @errors = AppError.unresolved
7
+ render json: @errors.map { |ae| AppErrorDecorator.new(ae).as_json }
8
+ end
9
+
10
+ def destroy
11
+ @error = AppError.find( params[:id] )
12
+ @error.resolved_at = Time.now
13
+ @error.save
14
+ render json: { ok: true }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module AutoError
2
+ class ApplicationController < ActionController::Base
3
+ include AutoError::ApplicationHelper
4
+ helper :all
5
+
6
+ private
7
+
8
+ def ensure_authenticated
9
+ context = AutoError::AuthContext.new(env)
10
+ raise AutoError::Errors::Denied unless AutoError::Config.auth_with.call(context)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module AutoError
2
+ class ErrorsController < ApplicationController
3
+
4
+ def show
5
+ # reset action_controller.instance to the original controller
6
+ # that caused the exception
7
+ env['action_controller.instance'] = env.delete('auto_error.original_controller.instance')
8
+
9
+ @exception = env['action_dispatch.exception']
10
+ @status_code = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
11
+ @rescue_response = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
12
+ @params = env['action_dispatch.request.parameters'].symbolize_keys
13
+
14
+ @status_code = 500 unless [403, 404].include?(@status_code)
15
+
16
+ if @status_code == 500
17
+ controller = "#{@params[:controller].camelize}Controller" rescue 'N/A'
18
+ action = @params[:action] || 'N/A'
19
+ where = { controller: controller, action: action }
20
+ data = {
21
+ path: env['REQUEST_URI'],
22
+ method: env['REQUEST_METHOD'],
23
+ ip: env['REMOTE_ADDR']
24
+ }
25
+ AppError.log!( env, @exception, where, data )
26
+ end
27
+
28
+ AutoError::Config.error_template_renderer.bind(self).( @status_code )
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ module AutoError
2
+ class MainController < ApplicationController
3
+ before_filter :ensure_authenticated
4
+
5
+ def index
6
+ render layout: 'auto_error/application'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module AutoError
2
+ class AppErrorDecorator < Draper::Decorator
3
+ def as_json
4
+ r = source.attributes
5
+ (r['data']||{}).entries.each do |k, v|
6
+ next if v.nil?
7
+ handler = AutoError::Config.data_handlers[k.to_sym].bind(ViewContext.new)
8
+ r['data'][k.to_s] = handler.(v).html_safe
9
+ end
10
+ r
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module AutoError
2
+ module ApplicationHelper
3
+ def js_namespace
4
+ h = {} # nothing needed, really
5
+ javascript_tag "window.App = #{h.to_json.html_safe};"
6
+ end
7
+
8
+ def void_path
9
+ 'javascript:void(0);'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,64 @@
1
+ module AutoError
2
+ class AppError < ActiveRecord::Base
3
+ before_create :generate_group
4
+
5
+ serialize :data
6
+
7
+ scope :unresolved, -> { where( resolved_at: nil ).order( 'created_at ASC' ) }
8
+
9
+ def self.log!( env, exception, opts, data={} )
10
+ opts[:data] = data
11
+ opts[:data].merge! self.context(env)
12
+ opts.merge!( {
13
+ klass: exception.class.name,
14
+ message: exception.message,
15
+ backtrace: (exception.backtrace || []).join("\n"),
16
+ } )
17
+ app_error = create!( opts )
18
+
19
+ if AutoError::Config.email_on_error.any?
20
+ begin
21
+ send_email!( env, exception )
22
+ rescue
23
+ $stderr.puts "AutoError failed to send exception notification email to #{AutoError::Config.email_on_error.inspect} -- #{$!.inspect}"
24
+ end
25
+ end
26
+
27
+ app_error
28
+ end
29
+
30
+ class << self
31
+ def add_context( env, opts )
32
+ context(env).merge!( opts )
33
+ end
34
+ def context( env )
35
+ env['auto_error.app_error.context'] ||= {}
36
+ env['auto_error.app_error.context']
37
+ end
38
+ def clear_context!( env )
39
+ env['auto_error.app_error.context'] = {}
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def self.send_email!( env, exception )
46
+ options = env['exception_notifier.options'] || {}
47
+ options[:ignore_exceptions] ||= ExceptionNotifier.default_ignore_exceptions
48
+ options[:email_prefix] ||= "[#{Rails.application.class.name.split('::').first} ERROR] "
49
+ options[:exception_recipients] = AutoError::Config.email_on_error
50
+
51
+ unless Array.wrap(options[:ignore_exceptions]).include?( exception.class )
52
+ ExceptionNotifier::Notifier.exception_notification( env, exception, options ).deliver
53
+ env['exception_notifier.delivered'] = true
54
+ end
55
+ end
56
+
57
+ def generate_group
58
+ self.group = Digest::SHA1.hexdigest( [
59
+ self.klass.to_s, self.message.to_s,
60
+ self.controller.to_s, self.action.to_s
61
+ ].join('-') ).to_s
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,32 @@
1
+ - content_for :auto_error_assets do
2
+ = stylesheet_link_tag 'auto_error/application', media: 'all'
3
+ = js_namespace
4
+ = javascript_include_tag 'auto_error/application'
5
+
6
+ .row#app_errors{ data: { url: app_errors_path } }
7
+ .twelve.columns.centered
8
+ %h2 App Errors
9
+
10
+ %table.polling{ width: '100%' }
11
+ %thead
12
+ %tr
13
+ %th{ width: '550px' } Message
14
+ %th Data
15
+ %th Time
16
+ %th &nbsp;
17
+ %tbody
18
+ %tr
19
+ %td{ colspan: 4 }
20
+ %p.loading_message Loading...
21
+ %tfoot
22
+ %tr
23
+ %td{ colspan: 4 }
24
+ .row
25
+ .six.columns
26
+ .poller
27
+ %a.tiny.button.radius.primary{ href: void_path } start polling
28
+ .spinner
29
+ .six.columns
30
+ %p.total
31
+ Total App Errors:
32
+ %strong &hellip;
@@ -0,0 +1 @@
1
+ Engine 404
@@ -0,0 +1 @@
1
+ Engine 500
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>AutoError AppErrors</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= yield :auto_error_assets %>
7
+ </head>
8
+ <body>
9
+ <%= yield %>
10
+ </body>
11
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,6 @@
1
+ if Rails.env.test?
2
+ require 'fabrication'
3
+ Fabrication.configure do |config|
4
+ config.path_prefix = AutoError::Engine.root
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ AutoError::Engine.routes.draw do
2
+ resources :app_errors
3
+ root to: 'main#index'
4
+ end
@@ -0,0 +1,19 @@
1
+ class CreateAutoErrorAppErrors < ActiveRecord::Migration
2
+ def change
3
+ create_table :auto_error_app_errors do |t|
4
+ t.string :group
5
+
6
+ t.string :klass
7
+ t.string :controller
8
+ t.string :action
9
+
10
+ t.string :message
11
+ t.text :backtrace
12
+ t.text :data
13
+
14
+ t.datetime :resolved_at, default: nil
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ # core ext
2
+ require 'core_ext/proc_ext'
3
+
4
+ # asset pipeline deps
5
+ require 'handlebars_assets'
6
+ require 'coffee_script'
7
+
8
+ # other deps
9
+ require 'jquery-rails'
10
+ require 'haml'
11
+ require 'draper'
12
+ require 'exception_notification'
13
+
14
+ # lib
15
+ require 'auto_error/version'
16
+ require 'auto_error/config'
17
+ require 'auto_error/errors'
18
+ require 'auto_error/context_shorthand'
19
+ require 'auto_error/view_context'
20
+ require 'auto_error/auth_context'
21
+ require 'auto_error/engine'
22
+
23
+ module AutoError
24
+ def self.setup!( app_config )
25
+ Config.send(:set_defaults)
26
+ app_config.action_dispatch.rescue_responses["AutoError::Errors::Denied"] = :forbidden
27
+ app_config.action_dispatch.rescue_responses["AutoError::Errors::NotFound"] = :not_found
28
+
29
+ original_exceptions_app = app_config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path)
30
+ app_config.exceptions_app = ->(env) do
31
+ # puts "Handling exception for #{env['action_controller.instance'].class}"
32
+ controller_class = env['action_controller.instance'].class
33
+ if controller_class.nil? || AutoError.constants.any? { |c| AutoError.const_get(c) == controller_class }
34
+ # do not log/handle exception at all if the error is actually
35
+ # IN auto_error :)
36
+ original_exceptions_app.call(env)
37
+ else
38
+ env['auto_error.original_controller.instance'] = env['action_controller.instance']
39
+ AutoError::ErrorsController.action(:show).call(env)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ module AutoError
2
+ class AuthContext
3
+ def initialize( env )
4
+ AutoError::Config.auth_helpers.each do |mod_name|
5
+ mod = Rails.application.class.qualified_const_get(mod_name)
6
+ class_eval do
7
+ send( :include, mod )
8
+ mod.instance_methods.each do |imeth|
9
+ alias :"#{imeth}_without_env" :"#{imeth}"
10
+ send( :define_method, imeth ) do
11
+ method( :"#{imeth}_without_env" ).to_proc.bind( env )
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ module AutoError
2
+ module Config
3
+ def self.setup( &blk )
4
+ yield self
5
+ end
6
+
7
+ mattr_accessor :auth_with
8
+ @@auth_with = nil
9
+
10
+ mattr_accessor :auth_helpers
11
+ @@auth_helpers = nil
12
+
13
+ mattr_accessor :email_on_error
14
+ @@email_on_error = nil
15
+
16
+ mattr_accessor :error_template_renderer
17
+ @@error_template_renderer = nil
18
+
19
+ mattr_accessor :data_handlers
20
+ @@data_handlers = nil
21
+
22
+ private
23
+
24
+ def self.set_defaults
25
+ self.setup do |config|
26
+ config.error_template_renderer = ->( status ) do
27
+ render template: "/errors/#{status}", layout: 'errors', status: status
28
+ end
29
+
30
+ config.email_on_error = []
31
+
32
+ config.auth_with = ->( c ) { true }
33
+ config.auth_helpers = [ 'ApplicationHelper' ]
34
+
35
+ config.data_handlers = Hash.new { |h, k| h[k] = ->( value ) { "<strong>#{value}</strong>" } }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module AutoError
2
+
3
+ # Convenience methods added to ApplicationController.
4
+ module ContextShorthand
5
+ def add_error_context( context )
6
+ AutoError::AppError.add_context( env, context )
7
+ end
8
+ def clear_error_context
9
+ AutoError::AppError.clear_context!( env )
10
+ end
11
+ end
12
+
13
+ ActionController::Base.send :include, AutoError::ContextShorthand
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ module AutoError
2
+ class Engine < ::Rails::Engine
3
+ engine_name 'AutoError'
4
+ isolate_namespace AutoError
5
+
6
+ config.exceptions_app = ->(env) { }
7
+
8
+ config.generators do |g|
9
+ g.test_framework :rspec, fixture: true
10
+ g.fixture_replacement :fabrication
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module AutoError
2
+ module Errors
3
+ class Denied < StandardError; end
4
+ class NotFound < StandardError; end
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module AutoError
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,10 @@
1
+ module AutoError
2
+ class ViewContext
3
+ def initialize
4
+ class_eval do
5
+ self.send( :include, ActionView::Helpers )
6
+ self.send( :include, Rails.application.routes.url_helpers )
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ class Proc
2
+ def bind(object)
3
+ block = self
4
+ object.class_eval do
5
+ method_name = :__proc_rebound_method__
6
+ method = nil
7
+ Thread.exclusive do
8
+ method_already_exists =
9
+ object.respond_to?(method_name) &&
10
+ instance_method(method_name).owner == self
11
+
12
+ old_method = instance_method(method_name) if method_already_exists
13
+
14
+ define_method(method_name, &block)
15
+ method = instance_method(method_name)
16
+ remove_method(method_name)
17
+
18
+ define_method(method_name, old_method) if method_already_exists
19
+ end
20
+ method
21
+ end.bind(object)
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :auto_error do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,11 @@
1
+ AutoError::Config.setup do |config|
2
+ # == Authenticated User Method
3
+ # Specify a Proc or :warden or :devise, depending on
4
+ # your authentication scheme.
5
+
6
+ # Examples:
7
+ #
8
+ # config.auth_with = Proc.new { |h| h.current_user }
9
+ # config.auth_with = :warden
10
+ config.auth_with = :warden
11
+ end
metadata ADDED
@@ -0,0 +1,311 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auto_error
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Funduk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: jquery-rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: haml
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: draper
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: exception_notification
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: sprockets-rails
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: coffee-rails
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: handlebars_assets
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: sqlite3
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: bcrypt-ruby
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: rspec-rails
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ - !ruby/object:Gem::Dependency
191
+ name: fabrication
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ! '>='
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ type: :development
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: faker
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: do_not_want
224
+ requirement: !ruby/object:Gem::Requirement
225
+ none: false
226
+ requirements:
227
+ - - ! '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ description: ! "\n AutoError is a mountable engine for Rails 3.2+ which provides\n
239
+ \ an 'exceptions_app' which helps you catch exceptions (showing\n the appropriate
240
+ page to users) and an interface you can mount\n in your admin panel to display
241
+ those errors.\n "
242
+ email: ryan.funduk@gmail.com
243
+ executables: []
244
+ extensions: []
245
+ extra_rdoc_files: []
246
+ files:
247
+ - app/assets/images/auto_error/spinner.gif
248
+ - app/assets/javascripts/auto_error/app_errors/configure.coffee
249
+ - app/assets/javascripts/auto_error/app_errors/index.coffee
250
+ - app/assets/javascripts/auto_error/app_errors/model.coffee
251
+ - app/assets/javascripts/auto_error/app_errors/views/app_errors.coffee
252
+ - app/assets/javascripts/auto_error/app_errors/views/base.coffee
253
+ - app/assets/javascripts/auto_error/application.js
254
+ - app/assets/stylesheets/auto_error/app_errors.css.erb
255
+ - app/assets/stylesheets/auto_error/application.css
256
+ - app/assets/templates/auto_error/app_error.hbs
257
+ - app/controllers/auto_error/app_errors_controller.rb
258
+ - app/controllers/auto_error/application_controller.rb
259
+ - app/controllers/auto_error/errors_controller.rb
260
+ - app/controllers/auto_error/main_controller.rb
261
+ - app/decorators/auto_error/app_error_decorator.rb
262
+ - app/helpers/auto_error/application_helper.rb
263
+ - app/models/auto_error/app_error.rb
264
+ - app/views/auto_error/main/index.html.haml
265
+ - app/views/errors/404.html.erb
266
+ - app/views/errors/500.html.erb
267
+ - app/views/layouts/auto_error/application.html.erb
268
+ - app/views/layouts/errors.html.erb
269
+ - config/initializers/fabrication.rb
270
+ - config/routes.rb
271
+ - db/migrate/20130128004546_create_auto_error_app_errors.rb
272
+ - lib/auto_error/auth_context.rb
273
+ - lib/auto_error/config.rb
274
+ - lib/auto_error/context_shorthand.rb
275
+ - lib/auto_error/engine.rb
276
+ - lib/auto_error/errors.rb
277
+ - lib/auto_error/version.rb
278
+ - lib/auto_error/view_context.rb
279
+ - lib/auto_error.rb
280
+ - lib/core_ext/proc_ext.rb
281
+ - lib/tasks/auto_error_tasks.rake
282
+ - lib/templates/auto_error.rb
283
+ - MIT-LICENSE
284
+ - Rakefile
285
+ - README.rdoc
286
+ homepage: http://ryanfunduk.com
287
+ licenses:
288
+ - MIT
289
+ post_install_message:
290
+ rdoc_options: []
291
+ require_paths:
292
+ - lib
293
+ required_ruby_version: !ruby/object:Gem::Requirement
294
+ none: false
295
+ requirements:
296
+ - - ! '>='
297
+ - !ruby/object:Gem::Version
298
+ version: 1.9.3
299
+ required_rubygems_version: !ruby/object:Gem::Requirement
300
+ none: false
301
+ requirements:
302
+ - - ! '>='
303
+ - !ruby/object:Gem::Version
304
+ version: '0'
305
+ requirements: []
306
+ rubyforge_project:
307
+ rubygems_version: 1.8.23
308
+ signing_key:
309
+ specification_version: 3
310
+ summary: A rails engine for in-app exception handling.
311
+ test_files: []