auto_error 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []