hoptoad_notifier 2.1.3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,41 @@
1
+ Version 2.2.0 - 2010-02-18
2
+ ===============================================================================
3
+
4
+ Bumping the version from 2.1.4 to 2.2.0 since adding Rack support warrants a minor version.
5
+
6
+ Jason Morrison (1):
7
+ Stringify array elements when making assertions about Notice XML for 1.9 compatibility
8
+
9
+
10
+ Version 2.1.4 - 2010-02-12
11
+ ===============================================================================
12
+
13
+ Chad Pytel (2):
14
+ add more info to README for 1.2.6
15
+ fix gem unpack line for 1.2.6
16
+
17
+ Jason Morrison (2):
18
+ Adding additional instructions for Rails 1.2.6
19
+ Typesetting in README.rdoc
20
+
21
+ Joe Ferris (11):
22
+ Separating Rails functionality out more
23
+ Initial Rack middleware
24
+ Extract request info from rack env
25
+ Added integration tests for rescuing
26
+ Fixed reporting of Rails version
27
+ Small refactoring
28
+ Automatically add Rack middleware for Rails apps that support it (catches exceptions from Metal)
29
+ Added an integration test and docs for rack apps
30
+ Added integration/readme coverage of Sinatra apps
31
+ Added docs to HoptoadNotifier::Rack
32
+ Require rack in tests for older versions of Rails; use active_support instead of activesupport
33
+
34
+ Nick Quaranto (3):
35
+ Fixing the capistrano hook bit in the readme
36
+ Adding changeling:minor and changeling:patch to automate notifier releases
37
+ Adding rake changeling:push
38
+
39
+
40
+
41
+
data/README.rdoc CHANGED
@@ -10,7 +10,7 @@ to the Hoptoad server specified in your environment.
10
10
  * {IRC}[irc://irc.freenode.net/thoughtbot]
11
11
  * {mailing list}[http://groups.google.com/group/hoptoad-notifier-dev]
12
12
 
13
- == Installation
13
+ == Rails Installation
14
14
 
15
15
  === Remove exception_notifier
16
16
 
@@ -48,15 +48,37 @@ every server you deploy to has the gem installed or your application won't start
48
48
 
49
49
  === Rails 1.2.6
50
50
 
51
- Install the hoptoad_notifier Gem, and then add something like this at the
52
- bottom of your config/environment.rb:
51
+ Install the hoptoad_notifier gem:
53
52
 
53
+ gem install hoptoad_notifier
54
+
55
+ Once installed, you should vendor the hoptoad_notifier gem:
56
+
57
+ mkdir vendor/gems
58
+ cd vendor/gems
59
+ gem unpack hoptoad_notifier
60
+
61
+ And then add the following to the Rails::Initializer.run do |config|
62
+ block in environment.rb so that the vendored gem is loaded.
63
+
64
+ # Add the vendor/gems/*/lib directories to the LOAD_PATH
65
+ config.load_paths += Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', '*', 'lib'))
66
+
67
+ Next add something like this at the bottom of your config/environment.rb:
68
+
69
+ require 'hoptoad_notifier'
70
+ require 'hoptoad_notifier/rails'
54
71
  HoptoadNotifier.configure do |config|
55
72
  config.api_key = 'your_key_here'
56
73
  end
57
74
 
58
- You will need to copy the hoptoad_notifier_tasks.rake file into your
59
- RAILS_ROOT/lib/tasks directory in order for the rake hoptoad:test task to work.
75
+ You will also need to copy the hoptoad_notifier_tasks.rake file into your
76
+ RAILS_ROOT/lib/tasks directory in order for the rake hoptoad:test task to work:
77
+
78
+ cp vendor/gems/hoptoad_notifier-2.1.3/generators/hoptoad/templates/hoptoad_notifier_tasks.rake lib/tasks
79
+
80
+ As always, if you choose not to vendor the hoptoad_notifier gem, make sure
81
+ every server you deploy to has the gem installed or your application won't start.
60
82
 
61
83
  === Testing it out
62
84
 
@@ -68,6 +90,45 @@ this rake task (from RAILS_ROOT):
68
90
  If everything is configured properly, that task will send a notice to Hoptoad
69
91
  which will be visible immediately.
70
92
 
93
+ == Rack
94
+
95
+ In order to use hoptoad_notifier in a non-Rails rack app, just load the
96
+ hoptoad_notifier, configure your API key, and use the HoptoadNotifier::Rack
97
+ middleware:
98
+
99
+ require 'rack'
100
+ require 'hoptoad_notifier'
101
+
102
+ HoptoadNotifier.configure do |config|
103
+ config.api_key = 'my_api_key'
104
+ end
105
+
106
+ app = Rack::Builder.app do
107
+ use HoptoadNotifier::Rack
108
+ run lambda { |env| raise "Rack down" }
109
+ end
110
+
111
+ == Sinatra
112
+
113
+ Using hoptoad_notifier in a Sinatra app is just like a Rack app, but you have
114
+ to disable Sinatra's error rescuing functionality:
115
+
116
+ require 'sinatra/base'
117
+ require 'hoptoad_notifier'
118
+
119
+ HoptoadNotifier.configure do |config|
120
+ config.api_key = 'my_api_key'
121
+ end
122
+
123
+ class MyApp < Sinatra::Default
124
+ use HoptoadNotifier::Rack
125
+ enable :raise_errors
126
+
127
+ get "/" do
128
+ raise "Sinatra has left the building"
129
+ end
130
+ end
131
+
71
132
  == Usage
72
133
 
73
134
  For the most part, Hoptoad works for itself. Once you've included the notifier
@@ -102,7 +163,7 @@ Additionally, it's possible to review the errors in Hoptoad that occurred before
102
163
 
103
164
  When Hoptoad is installed as a gem, you need to add
104
165
 
105
- require 'hoptoad_notifier/recipes/hoptoad'
166
+ require 'hoptoad_notifier/capistrano'
106
167
 
107
168
  to your deploy.rb
108
169
 
data/Rakefile CHANGED
@@ -22,6 +22,83 @@ task :ginger do
22
22
  load File.join(*%w[vendor ginger bin ginger])
23
23
  end
24
24
 
25
+ namespace :changeling do
26
+ desc "Bumps the version by a minor or patch version, depending on what was passed in."
27
+ task :bump, :part do |t, args|
28
+ # Thanks, Jeweler!
29
+ if HoptoadNotifier::VERSION =~ /^(\d+)\.(\d+)\.(\d+)(?:\.(.*?))?$/
30
+ major = $1.to_i
31
+ minor = $2.to_i
32
+ patch = $3.to_i
33
+ build = $4
34
+ else
35
+ abort
36
+ end
37
+
38
+ case args[:part]
39
+ when /minor/
40
+ minor += 1
41
+ patch = 0
42
+ when /patch/
43
+ patch += 1
44
+ else
45
+ abort
46
+ end
47
+
48
+ version = [major, minor, patch, build].compact.join('.')
49
+
50
+ File.open(File.join("lib", "hoptoad_notifier", "version.rb"), "w") do |f|
51
+ f.write <<EOF
52
+ module HoptoadNotifier
53
+ VERSION = "#{version}".freeze
54
+ end
55
+ EOF
56
+ end
57
+ end
58
+
59
+ desc "Writes out the new CHANGELOG and prepares the release"
60
+ task :change do
61
+ load 'lib/hoptoad_notifier/version.rb'
62
+ file = "CHANGELOG"
63
+ old = File.read(file)
64
+ version = HoptoadNotifier::VERSION
65
+ message = "Bumping to version #{version}"
66
+
67
+ File.open(file, "w") do |f|
68
+ f.write <<EOF
69
+ Version #{version} - #{Date.today}
70
+ ===============================================================================
71
+
72
+ #{`git log $(git tag | tail -1)..HEAD | git shortlog`}
73
+ #{old}
74
+ EOF
75
+ end
76
+
77
+ exec ["#{ENV["EDITOR"]} #{file}",
78
+ "git commit -aqm '#{message}'",
79
+ "git tag -a -m '#{message}' v#{version}",
80
+ "echo '\n\n\033[32mMarked v#{version} /' `git show-ref -s refs/heads/master` 'for release. Run: rake changeling:push\033[0m\n\n'"].join(' && ')
81
+ end
82
+
83
+ desc "Bump by a minor version (1.2.3 => 1.3.0)"
84
+ task :minor do |t|
85
+ Rake::Task['changeling:bump'].invoke(t.name)
86
+ Rake::Task['changeling:change'].invoke
87
+ end
88
+
89
+ desc "Bump by a patch version, (1.2.3 => 1.2.4)"
90
+ task :patch do |t|
91
+ Rake::Task['changeling:bump'].invoke(t.name)
92
+ Rake::Task['changeling:change'].invoke
93
+ end
94
+
95
+ desc "Push the latest version and tags"
96
+ task :push do |t|
97
+ system("git push origin master")
98
+ system("git push origin $(git tag | tail -1)")
99
+ end
100
+ end
101
+
25
102
  begin
26
103
  require 'yard'
27
104
  YARD::Rake::YardocTask.new do |t|
@@ -81,7 +158,7 @@ end
81
158
 
82
159
  LOCAL_GEM_ROOT = File.join(GEM_ROOT, 'tmp', 'local_gems').freeze
83
160
  RAILS_VERSIONS = IO.read('SUPPORTED_RAILS_VERSIONS').strip.split("\n")
84
- LOCAL_GEMS = [['sham_rack', nil], ['capistrano', nil], ['sqlite3-ruby', nil]] +
161
+ LOCAL_GEMS = [['sham_rack', nil], ['capistrano', nil], ['sqlite3-ruby', nil], ['sinatra', nil]] +
85
162
  RAILS_VERSIONS.collect { |version| ['rails', version] }
86
163
 
87
164
  task :vendor_test_gems do
@@ -107,19 +184,18 @@ end
107
184
 
108
185
  task :cucumber => [:gemspec, :vendor_test_gems]
109
186
 
110
- OLD_RAILS_VERSIONS = RAILS_VERSIONS[0...-1]
111
-
112
187
  namespace :cucumber do
113
188
  namespace :rails do
114
- OLD_RAILS_VERSIONS.each do |version|
189
+ RAILS_VERSIONS.each do |version|
115
190
  desc "Test integration of the gem with Rails #{version}"
116
191
  task version do
192
+ puts "Testing Rails #{version}"
117
193
  ENV['RAILS_VERSION'] = version
118
194
  system("cucumber --format progress features/rails.feature")
119
195
  end
120
196
  end
121
197
 
122
198
  desc "Test integration of the gem with all Rails versions"
123
- task :all => [:cucumber, *OLD_RAILS_VERSIONS]
199
+ task :all => RAILS_VERSIONS
124
200
  end
125
201
  end
@@ -6,8 +6,8 @@ require 'hoptoad_notifier/version'
6
6
  require 'hoptoad_notifier/configuration'
7
7
  require 'hoptoad_notifier/notice'
8
8
  require 'hoptoad_notifier/sender'
9
- require 'hoptoad_notifier/catcher'
10
9
  require 'hoptoad_notifier/backtrace'
10
+ require 'hoptoad_notifier/rack'
11
11
 
12
12
  # Gem for applications to automatically post errors to the Hoptoad of their choice.
13
13
  module HoptoadNotifier
@@ -47,7 +47,7 @@ module HoptoadNotifier
47
47
  # Returns the Ruby version, Rails version, and current Rails environment
48
48
  def environment_info
49
49
  info = "[Ruby: #{RUBY_VERSION}]"
50
- info << " [Rails: #{::Rails::VERSION::STRING}]" if defined?(Rails)
50
+ info << " [#{configuration.framework}]"
51
51
  info << " [Env: #{configuration.environment_name}]"
52
52
  end
53
53
 
@@ -7,7 +7,7 @@ module HoptoadNotifier
7
7
  :http_open_timeout, :http_read_timeout, :ignore, :ignore_by_filters,
8
8
  :ignore_user_agent, :notifier_name, :notifier_url, :notifier_version,
9
9
  :params_filters, :project_root, :port, :protocol, :proxy_host,
10
- :proxy_pass, :proxy_port, :proxy_user, :secure].freeze
10
+ :proxy_pass, :proxy_port, :proxy_user, :secure, :framework].freeze
11
11
 
12
12
  # The API key for your project, found on the project edit form.
13
13
  attr_accessor :api_key
@@ -80,6 +80,9 @@ module HoptoadNotifier
80
80
  # The logger used by HoptoadNotifier
81
81
  attr_accessor :logger
82
82
 
83
+ # The framework HoptoadNotifier is configured to use
84
+ attr_accessor :framework
85
+
83
86
  DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
84
87
 
85
88
  DEFAULT_BACKTRACE_FILTERS = [
@@ -124,6 +127,7 @@ module HoptoadNotifier
124
127
  @notifier_name = 'Hoptoad Notifier'
125
128
  @notifier_version = VERSION
126
129
  @notifier_url = 'http://hoptoadapp.com'
130
+ @framework = 'Standalone'
127
131
  end
128
132
 
129
133
  # Takes a block and adds it to the list of backtrace filters. When the filters
@@ -68,7 +68,7 @@ module HoptoadNotifier
68
68
  self.exception = args[:exception]
69
69
  self.api_key = args[:api_key]
70
70
  self.project_root = args[:project_root]
71
- self.url = args[:url]
71
+ self.url = args[:url] || rack_env(:url)
72
72
 
73
73
  self.notifier_name = args[:notifier_name]
74
74
  self.notifier_version = args[:notifier_version]
@@ -78,12 +78,12 @@ module HoptoadNotifier
78
78
  self.ignore_by_filters = args[:ignore_by_filters] || []
79
79
  self.backtrace_filters = args[:backtrace_filters] || []
80
80
  self.params_filters = args[:params_filters] || []
81
- self.parameters = args[:parameters] || {}
81
+ self.parameters = args[:parameters] || rack_env(:params) || {}
82
82
  self.component = args[:component] || args[:controller]
83
83
  self.action = args[:action]
84
84
 
85
85
  self.environment_name = args[:environment_name]
86
- self.cgi_data = args[:cgi_data]
86
+ self.cgi_data = args[:cgi_data] || args[:rack_env]
87
87
  self.backtrace = Backtrace.parse(exception_attribute(:backtrace, caller), :filters => self.backtrace_filters)
88
88
  self.error_class = exception_attribute(:error_class) {|exception| exception.class.name }
89
89
  self.error_message = exception_attribute(:error_message, 'Notification') do |exception|
@@ -291,5 +291,15 @@ module HoptoadNotifier
291
291
  end
292
292
  end
293
293
  end
294
+
295
+ def rack_env(method)
296
+ rack_request.send(method) if rack_request
297
+ end
298
+
299
+ def rack_request
300
+ @rack_request ||= if args[:rack_env]
301
+ ::Rack::Request.new(args[:rack_env])
302
+ end
303
+ end
294
304
  end
295
305
  end
@@ -0,0 +1,40 @@
1
+ module HoptoadNotifier
2
+ # Middleware for Rack applications. Any errors raised by the upstream
3
+ # application will be delivered to Hoptoad and re-raised.
4
+ #
5
+ # Synopsis:
6
+ #
7
+ # require 'rack'
8
+ # require 'hoptoad_notifier'
9
+ #
10
+ # HoptoadNotifier.configure do |config|
11
+ # config.api_key = 'my_api_key'
12
+ # end
13
+ #
14
+ # app = Rack::Builder.app do
15
+ # use HoptoadNotifier::Rack
16
+ # run lambda { |env| raise "Rack down" }
17
+ # end
18
+ #
19
+ # Use a standard HoptoadNotifier.configure call to configure your api key.
20
+ class Rack
21
+ def initialize(app)
22
+ @app = app
23
+ end
24
+
25
+ def call(env)
26
+ begin
27
+ response = @app.call(env)
28
+ rescue Exception => raised
29
+ HoptoadNotifier.notify_or_ignore(raised, :rack_env => env)
30
+ raise
31
+ end
32
+
33
+ if env['rack.exception']
34
+ HoptoadNotifier.notify_or_ignore(env['rack.exception'], :rack_env => env)
35
+ end
36
+
37
+ response
38
+ end
39
+ end
40
+ end
@@ -1,11 +1,37 @@
1
- if defined?(ActionController::Base) && !ActionController::Base.include?(HoptoadNotifier::Catcher)
2
- ActionController::Base.send(:include, HoptoadNotifier::Catcher)
3
- end
1
+ require 'hoptoad_notifier'
2
+ require 'hoptoad_notifier/rails/controller_methods'
3
+ require 'hoptoad_notifier/rails/action_controller_catcher'
4
+ require 'hoptoad_notifier/rails/error_lookup'
5
+
6
+ module HoptoadNotifier
7
+ module Rails
8
+ def self.initialize
9
+ if defined?(ActionController::Base)
10
+ ActionController::Base.send(:include, HoptoadNotifier::Rails::ActionControllerCatcher)
11
+ ActionController::Base.send(:include, HoptoadNotifier::Rails::ErrorLookup)
12
+ ActionController::Base.send(:include, HoptoadNotifier::Rails::ControllerMethods)
13
+ end
14
+
15
+ rails_logger = if defined?(::Rails.logger)
16
+ ::Rails.logger
17
+ elsif defined?(RAILS_DEFAULT_LOGGER)
18
+ RAILS_DEFAULT_LOGGER
19
+ end
4
20
 
5
- require 'hoptoad_notifier/rails_initializer'
6
- HoptoadNotifier::RailsInitializer.initialize
21
+ if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
22
+ ::Rails.configuration.middleware.insert_after 'ActionController::Failsafe',
23
+ HoptoadNotifier::Rack
24
+ end
7
25
 
8
- HoptoadNotifier.configure(true) do |config|
9
- config.environment_name = RAILS_ENV
10
- config.project_root = RAILS_ROOT
26
+ HoptoadNotifier.configure(true) do |config|
27
+ config.logger = rails_logger
28
+ config.environment_name = RAILS_ENV if defined?(RAILS_ENV)
29
+ config.project_root = RAILS_ROOT if defined?(RAILS_ROOT)
30
+ config.framework = "Rails: #{::Rails::VERSION::STRING}" if defined?(::Rails::VERSION)
31
+ end
32
+ end
33
+ end
11
34
  end
35
+
36
+ HoptoadNotifier::Rails.initialize
37
+
@@ -0,0 +1,29 @@
1
+ module HoptoadNotifier
2
+ module Rails
3
+ module ActionControllerCatcher
4
+
5
+ # Sets up an alias chain to catch exceptions when Rails does
6
+ def self.included(base) #:nodoc:
7
+ base.send(:alias_method, :rescue_action_in_public_without_hoptoad, :rescue_action_in_public)
8
+ base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_hoptoad)
9
+ end
10
+
11
+ private
12
+
13
+ # Overrides the rescue_action method in ActionController::Base, but does not inhibit
14
+ # any custom processing that is defined with Rails 2's exception helpers.
15
+ def rescue_action_in_public_with_hoptoad(exception)
16
+ unless hoptoad_ignore_user_agent?
17
+ HoptoadNotifier.notify_or_ignore(exception, hoptoad_request_data)
18
+ end
19
+ rescue_action_in_public_without_hoptoad(exception)
20
+ end
21
+
22
+ def hoptoad_ignore_user_agent? #:nodoc:
23
+ # Rails 1.2.6 doesn't have request.user_agent, so check for it here
24
+ user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
25
+ HoptoadNotifier.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,59 @@
1
+ module HoptoadNotifier
2
+ module Rails
3
+ module ControllerMethods
4
+ private
5
+
6
+ # This method should be used for sending manual notifications while you are still
7
+ # inside the controller. Otherwise it works like HoptoadNotifier.notify.
8
+ def notify_hoptoad(hash_or_exception)
9
+ unless consider_all_requests_local || local_request?
10
+ HoptoadNotifier.notify(hash_or_exception, hoptoad_request_data)
11
+ end
12
+ end
13
+
14
+ def hoptoad_ignore_user_agent? #:nodoc:
15
+ # Rails 1.2.6 doesn't have request.user_agent, so check for it here
16
+ user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
17
+ HoptoadNotifier.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
18
+ end
19
+
20
+ def hoptoad_request_data
21
+ { :parameters => hoptoad_filter_if_filtering(params.to_hash),
22
+ :session_data => hoptoad_session_data,
23
+ :controller => params[:controller],
24
+ :action => params[:action],
25
+ :url => hoptoad_request_url,
26
+ :cgi_data => hoptoad_filter_if_filtering(request.env),
27
+ :environment_vars => hoptoad_filter_if_filtering(ENV) }
28
+ end
29
+
30
+ def hoptoad_filter_if_filtering(hash)
31
+ if respond_to?(:filter_parameters)
32
+ filter_parameters(hash) rescue hash
33
+ else
34
+ hash
35
+ end
36
+ end
37
+
38
+ def hoptoad_session_data
39
+ if session.respond_to?(:to_hash)
40
+ session.to_hash
41
+ else
42
+ session.data
43
+ end
44
+ end
45
+
46
+ def hoptoad_request_url
47
+ url = "#{request.protocol}#{request.host}"
48
+
49
+ unless [80, 443].include?(request.port)
50
+ url << ":#{request.port}"
51
+ end
52
+
53
+ url << request.request_uri
54
+ url
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,33 @@
1
+ module HoptoadNotifier
2
+ module Rails
3
+ module ErrorLookup
4
+
5
+ # Sets up an alias chain to catch exceptions when Rails does
6
+ def self.included(base) #:nodoc:
7
+ base.send(:alias_method, :rescue_action_locally_without_hoptoad, :rescue_action_locally)
8
+ base.send(:alias_method, :rescue_action_locally, :rescue_action_locally_with_hoptoad)
9
+ end
10
+
11
+ private
12
+
13
+ def rescue_action_locally_with_hoptoad(exception)
14
+ result = rescue_action_locally_without_hoptoad(exception)
15
+
16
+ if HoptoadNotifier.configuration.development_lookup
17
+ path = File.join(File.dirname(__FILE__), '..', '..', 'templates', 'rescue.erb')
18
+ notice = HoptoadNotifier.build_lookup_hash_for(exception, hoptoad_request_data)
19
+
20
+ result << @template.render(
21
+ :file => path,
22
+ :use_full_path => false,
23
+ :locals => { :host => HoptoadNotifier.configuration.host,
24
+ :api_key => HoptoadNotifier.configuration.api_key,
25
+ :notice => notice })
26
+ end
27
+
28
+ result
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -21,10 +21,8 @@ namespace :hoptoad do
21
21
  RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
22
22
 
23
23
  require 'action_controller/test_process'
24
- require 'app/controllers/application' if File.exists?('app/controllers/application.rb')
25
24
 
26
- request = ActionController::TestRequest.new
27
- response = ActionController::TestResponse.new
25
+ Dir["app/controllers/application*.rb"].each { |file| require(file) }
28
26
 
29
27
  class HoptoadTestingException < RuntimeError; end
30
28
 
@@ -35,10 +33,11 @@ namespace :hoptoad do
35
33
 
36
34
  HoptoadNotifier.configuration.development_environments = []
37
35
 
38
- in_controller = ApplicationController.included_modules.include? HoptoadNotifier::Catcher
39
- in_base = ActionController::Base.included_modules.include? HoptoadNotifier::Catcher
36
+ catcher = HoptoadNotifier::Rails::ActionControllerCatcher
37
+ in_controller = ApplicationController.included_modules.include?(catcher)
38
+ in_base = ActionController::Base.included_modules.include?(catcher)
40
39
  if !in_controller || !in_base
41
- puts "HoptoadNotifier::Catcher must be included inside your ApplicationController class."
40
+ puts "Rails initialization did not occur"
42
41
  exit
43
42
  end
44
43
 
@@ -47,6 +46,11 @@ namespace :hoptoad do
47
46
  puts sprintf("%25s: %s", key.to_s, value.inspect.slice(0, 55))
48
47
  end
49
48
 
49
+ unless defined?(ApplicationController)
50
+ puts "No ApplicationController found"
51
+ exit
52
+ end
53
+
50
54
  puts 'Setting up the Controller.'
51
55
  class ApplicationController
52
56
  # This is to bypass any filters that may prevent access to the action.
@@ -56,7 +60,7 @@ namespace :hoptoad do
56
60
  raise exception_class.new, 'Testing hoptoad via "rake hoptoad:test". If you can see this, it works.'
57
61
  end
58
62
 
59
- def rescue_action exception
63
+ def rescue_action(exception)
60
64
  rescue_action_in_public exception
61
65
  end
62
66
 
@@ -82,9 +86,11 @@ namespace :hoptoad do
82
86
  nil
83
87
  end
84
88
  end
89
+ class HoptoadVerificationController < ApplicationController; end
85
90
 
86
91
  puts 'Processing request.'
87
- class HoptoadVerificationController < ApplicationController; end
92
+ request = ActionController::TestRequest.new
93
+ response = ActionController::TestResponse.new
88
94
  HoptoadVerificationController.new.process(request, response)
89
95
  end
90
96
  end
@@ -1,3 +1,3 @@
1
1
  module HoptoadNotifier
2
- VERSION = "2.1.3".freeze
2
+ VERSION = "2.2.0".freeze
3
3
  end
data/test/catcher_test.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- class CatcherTest < Test::Unit::TestCase
3
+ class ActionControllerCatcherTest < Test::Unit::TestCase
4
4
 
5
5
  include DefinesConstants
6
6
 
@@ -17,7 +17,7 @@ class CatcherTest < Test::Unit::TestCase
17
17
 
18
18
  def build_controller_class(&definition)
19
19
  returning Class.new(ActionController::Base) do |klass|
20
- klass.__send__(:include, HoptoadNotifier::Catcher)
20
+ klass.__send__(:include, HoptoadNotifier::Rails::ActionControllerCatcher)
21
21
  klass.class_eval(&definition) if definition
22
22
  define_constant('HoptoadTestController', klass)
23
23
  end
@@ -29,13 +29,23 @@ class CatcherTest < Test::Unit::TestCase
29
29
  if value.respond_to?(:to_hash)
30
30
  assert_sent_hash value.to_hash, element_xpath
31
31
  else
32
- assert_sent_element value.to_s, element_xpath
32
+ assert_sent_element value, element_xpath
33
33
  end
34
34
  end
35
35
  end
36
36
 
37
37
  def assert_sent_element(value, xpath)
38
- assert_valid_node last_sent_notice_document, xpath, value
38
+ assert_valid_node last_sent_notice_document, xpath, stringify_array_elements(value).to_s
39
+ end
40
+
41
+ def stringify_array_elements(data)
42
+ if data.respond_to?(:to_ary)
43
+ data.collect do |value|
44
+ stringify_array_elements(value)
45
+ end
46
+ else
47
+ data.to_s
48
+ end
39
49
  end
40
50
 
41
51
  def assert_sent_request_info_for(request)
@@ -172,7 +182,7 @@ class CatcherTest < Test::Unit::TestCase
172
182
 
173
183
  should "not create actions from Hoptoad methods" do
174
184
  controller = build_controller_class.new
175
- assert_equal [], HoptoadNotifier::Catcher.instance_methods
185
+ assert_equal [], HoptoadNotifier::Rails::ActionControllerCatcher.instance_methods
176
186
  end
177
187
 
178
188
  should "ignore exceptions when user agent is being ignored by regular expression" do
@@ -28,6 +28,7 @@ class ConfigurationTest < Test::Unit::TestCase
28
28
  assert_config_default :ignore,
29
29
  HoptoadNotifier::Configuration::IGNORE_DEFAULT
30
30
  assert_config_default :development_lookup, true
31
+ assert_config_default :framework, 'Standalone'
31
32
  end
32
33
 
33
34
  should "provide default values for secure connections" do
data/test/helper.rb CHANGED
@@ -3,10 +3,12 @@ require 'rubygems'
3
3
 
4
4
  gem 'jferris-mocha', '>= 0.9.5.0.1241126838'
5
5
 
6
+ $LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. vendor ginger lib])
7
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
8
+
6
9
  require 'shoulda'
7
10
  require 'mocha'
8
11
 
9
- $LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. vendor ginger lib])
10
12
  require 'ginger'
11
13
 
12
14
  require 'action_controller'
@@ -15,8 +17,9 @@ require 'active_record'
15
17
  require 'active_record/base'
16
18
  require 'active_support'
17
19
  require 'nokogiri'
20
+ require 'rack'
18
21
 
19
- require File.join(File.dirname(__FILE__), "..", "lib", "hoptoad_notifier")
22
+ require "hoptoad_notifier"
20
23
 
21
24
  begin require 'redgreen'; rescue LoadError; end
22
25
 
@@ -234,4 +237,3 @@ class FakeLogger
234
237
  def fatal(*args); end
235
238
  end
236
239
 
237
- RAILS_DEFAULT_LOGGER = FakeLogger.new
data/test/notice_test.rb CHANGED
@@ -143,7 +143,7 @@ class NoticeTest < Test::Unit::TestCase
143
143
  end
144
144
 
145
145
  should "use the caller as the backtrace for an exception without a backtrace" do
146
- filters = HoptoadNotifier.configuration.backtrace_filters
146
+ filters = HoptoadNotifier::Configuration.new.backtrace_filters
147
147
  backtrace = HoptoadNotifier::Backtrace.parse(caller, :filters => filters)
148
148
  notice = build_notice(:exception => StandardError.new('error'), :backtrace => nil)
149
149
 
@@ -338,6 +338,21 @@ class NoticeTest < Test::Unit::TestCase
338
338
  end
339
339
  end
340
340
 
341
+ should "extract data from a rack environment hash" do
342
+ # TODO: extract session data
343
+ # TODO: extract controller
344
+ # TODO: extract action
345
+ url = "https://subdomain.happylane.com:100/test/file.rb?var=value&var2=value2"
346
+ parameters = { 'var' => 'value', 'var2' => 'value2' }
347
+ env = Rack::MockRequest.env_for(url)
348
+
349
+ notice = build_notice(:rack_env => env)
350
+
351
+ assert_equal url, notice.url
352
+ assert_equal parameters, notice.parameters
353
+ assert_equal 'GET', notice.cgi_data['REQUEST_METHOD']
354
+ end
355
+
341
356
  def assert_accepts_exception_attribute(attribute, args = {}, &block)
342
357
  exception = build_exception
343
358
  block ||= lambda { exception.send(attribute) }
data/test/rack_test.rb ADDED
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class RackTest < Test::Unit::TestCase
4
+
5
+ should "call the upstream app with the environment" do
6
+ environment = { 'key' => 'value' }
7
+ app = lambda { |env| ['response', {}, env] }
8
+ stack = HoptoadNotifier::Rack.new(app)
9
+
10
+ response = stack.call(environment)
11
+
12
+ assert_equal ['response', {}, environment], response
13
+ end
14
+
15
+ should "deliver an exception raised while calling an upstream app" do
16
+ HoptoadNotifier.stubs(:notify_or_ignore)
17
+
18
+ exception = build_exception
19
+ environment = { 'key' => 'value' }
20
+ app = lambda do |env|
21
+ raise exception
22
+ end
23
+
24
+ begin
25
+ stack = HoptoadNotifier::Rack.new(app)
26
+ stack.call(environment)
27
+ rescue Exception => raised
28
+ assert_equal exception, raised
29
+ else
30
+ flunk "Didn't raise an exception"
31
+ end
32
+
33
+ assert_received(HoptoadNotifier, :notify_or_ignore) do |expect|
34
+ expect.with(exception, :rack_env => environment)
35
+ end
36
+ end
37
+
38
+ should "deliver an exception in rack.exception" do
39
+ HoptoadNotifier.stubs(:notify_or_ignore)
40
+ exception = build_exception
41
+ environment = { 'key' => 'value' }
42
+
43
+ response = [200, {}, ['okay']]
44
+ app = lambda do |env|
45
+ env['rack.exception'] = exception
46
+ response
47
+ end
48
+ stack = HoptoadNotifier::Rack.new(app)
49
+
50
+ actual_response = stack.call(environment)
51
+
52
+ assert_equal response, actual_response
53
+ assert_received(HoptoadNotifier, :notify_or_ignore) do |expect|
54
+ expect.with(exception, :rack_env => environment)
55
+ end
56
+ end
57
+
58
+ end
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
- require File.join(File.dirname(__FILE__), '..', 'lib', 'hoptoad_notifier', 'rails_initializer')
2
+
3
+ require 'hoptoad_notifier/rails'
3
4
 
4
5
  class RailsInitializerTest < Test::Unit::TestCase
5
6
  include DefinesConstants
@@ -11,20 +12,20 @@ class RailsInitializerTest < Test::Unit::TestCase
11
12
  end
12
13
  end
13
14
  define_constant("Rails", rails)
14
- HoptoadNotifier::RailsInitializer.initialize
15
+ HoptoadNotifier::Rails.initialize
15
16
  assert_equal "RAILS LOGGER", HoptoadNotifier.logger
16
17
  end
17
18
 
18
19
  should "trigger use of Rails' default logger if logger isn't set and Rails.logger doesn't exist" do
19
20
  define_constant("RAILS_DEFAULT_LOGGER", "RAILS DEFAULT LOGGER")
20
21
 
21
- HoptoadNotifier::RailsInitializer.initialize
22
+ HoptoadNotifier::Rails.initialize
22
23
  assert_equal "RAILS DEFAULT LOGGER", HoptoadNotifier.logger
23
24
  end
24
25
 
25
26
  should "allow overriding of the logger if already assigned" do
26
27
  define_constant("RAILS_DEFAULT_LOGGER", "RAILS DEFAULT LOGGER")
27
- HoptoadNotifier::RailsInitializer.initialize
28
+ HoptoadNotifier::Rails.initialize
28
29
 
29
30
  HoptoadNotifier.configure(true) do |config|
30
31
  config.logger = "OVERRIDDEN LOGGER"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoptoad_notifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot, inc
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-27 00:00:00 -05:00
12
+ date: 2010-02-18 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -81,6 +81,7 @@ extensions: []
81
81
  extra_rdoc_files:
82
82
  - README.rdoc
83
83
  files:
84
+ - CHANGELOG
84
85
  - INSTALL
85
86
  - MIT-LICENSE
86
87
  - Rakefile
@@ -95,11 +96,13 @@ files:
95
96
  - generators/hoptoad/templates/initializer.rb
96
97
  - lib/hoptoad_notifier/backtrace.rb
97
98
  - lib/hoptoad_notifier/capistrano.rb
98
- - lib/hoptoad_notifier/catcher.rb
99
99
  - lib/hoptoad_notifier/configuration.rb
100
100
  - lib/hoptoad_notifier/notice.rb
101
+ - lib/hoptoad_notifier/rack.rb
102
+ - lib/hoptoad_notifier/rails/action_controller_catcher.rb
103
+ - lib/hoptoad_notifier/rails/controller_methods.rb
104
+ - lib/hoptoad_notifier/rails/error_lookup.rb
101
105
  - lib/hoptoad_notifier/rails.rb
102
- - lib/hoptoad_notifier/rails_initializer.rb
103
106
  - lib/hoptoad_notifier/sender.rb
104
107
  - lib/hoptoad_notifier/tasks.rb
105
108
  - lib/hoptoad_notifier/version.rb
@@ -113,6 +116,7 @@ files:
113
116
  - test/logger_test.rb
114
117
  - test/notice_test.rb
115
118
  - test/notifier_test.rb
119
+ - test/rack_test.rb
116
120
  - test/rails_initializer_test.rb
117
121
  - test/sender_test.rb
118
122
  - rails/init.rb
@@ -156,5 +160,6 @@ test_files:
156
160
  - test/logger_test.rb
157
161
  - test/notice_test.rb
158
162
  - test/notifier_test.rb
163
+ - test/rack_test.rb
159
164
  - test/rails_initializer_test.rb
160
165
  - test/sender_test.rb
@@ -1,95 +0,0 @@
1
- module HoptoadNotifier
2
- # Include this module in Controllers in which you want to be notified of errors.
3
- module Catcher
4
-
5
- # Sets up an alias chain to catch exceptions when Rails does
6
- def self.included(base) #:nodoc:
7
- if base.instance_methods.map(&:to_s).include? 'rescue_action_in_public' and !base.instance_methods.map(&:to_s).include? 'rescue_action_in_public_without_hoptoad'
8
- base.send(:alias_method, :rescue_action_in_public_without_hoptoad, :rescue_action_in_public)
9
- base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_hoptoad)
10
- base.send(:alias_method, :rescue_action_locally_without_hoptoad, :rescue_action_locally)
11
- base.send(:alias_method, :rescue_action_locally, :rescue_action_locally_with_hoptoad)
12
- end
13
- end
14
-
15
- private
16
-
17
- # Overrides the rescue_action method in ActionController::Base, but does not inhibit
18
- # any custom processing that is defined with Rails 2's exception helpers.
19
- def rescue_action_in_public_with_hoptoad(exception)
20
- unless hoptoad_ignore_user_agent?
21
- HoptoadNotifier.notify_or_ignore(exception, hoptoad_request_data)
22
- end
23
- rescue_action_in_public_without_hoptoad(exception)
24
- end
25
-
26
- def rescue_action_locally_with_hoptoad(exception)
27
- result = rescue_action_locally_without_hoptoad(exception)
28
-
29
- if HoptoadNotifier.configuration.development_lookup
30
- path = File.join(File.dirname(__FILE__), '..', 'templates', 'rescue.erb')
31
- notice = HoptoadNotifier.build_lookup_hash_for(exception, hoptoad_request_data)
32
-
33
- result << @template.render(
34
- :file => path,
35
- :use_full_path => false,
36
- :locals => { :host => HoptoadNotifier.configuration.host,
37
- :api_key => HoptoadNotifier.configuration.api_key,
38
- :notice => notice })
39
- end
40
-
41
- result
42
- end
43
-
44
- # This method should be used for sending manual notifications while you are still
45
- # inside the controller. Otherwise it works like HoptoadNotifier.notify.
46
- def notify_hoptoad(hash_or_exception)
47
- unless consider_all_requests_local || local_request?
48
- HoptoadNotifier.notify(hash_or_exception, hoptoad_request_data)
49
- end
50
- end
51
-
52
- def hoptoad_ignore_user_agent? #:nodoc:
53
- # Rails 1.2.6 doesn't have request.user_agent, so check for it here
54
- user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
55
- HoptoadNotifier.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
56
- end
57
-
58
- def hoptoad_request_data
59
- { :parameters => hoptoad_filter_if_filtering(params.to_hash),
60
- :session_data => hoptoad_session_data,
61
- :controller => params[:controller],
62
- :action => params[:action],
63
- :url => hoptoad_request_url,
64
- :cgi_data => hoptoad_filter_if_filtering(request.env),
65
- :environment_vars => hoptoad_filter_if_filtering(ENV) }
66
- end
67
-
68
- def hoptoad_filter_if_filtering(hash)
69
- if respond_to?(:filter_parameters)
70
- filter_parameters(hash) rescue hash
71
- else
72
- hash
73
- end
74
- end
75
-
76
- def hoptoad_session_data
77
- if session.respond_to?(:to_hash)
78
- session.to_hash
79
- else
80
- session.data
81
- end
82
- end
83
-
84
- def hoptoad_request_url
85
- url = "#{request.protocol}#{request.host}"
86
-
87
- unless [80, 443].include?(request.port)
88
- url << ":#{request.port}"
89
- end
90
-
91
- url << request.request_uri
92
- url
93
- end
94
- end
95
- end
@@ -1,16 +0,0 @@
1
- module HoptoadNotifier
2
- # used to initialize Rails-specific code
3
- class RailsInitializer
4
- def self.initialize
5
- rails_logger = if defined?(Rails.logger)
6
- Rails.logger
7
- elsif defined?(RAILS_DEFAULT_LOGGER)
8
- RAILS_DEFAULT_LOGGER
9
- end
10
-
11
- HoptoadNotifier.configure(true) do |config|
12
- config.logger = rails_logger if config.respond_to? :logger
13
- end
14
- end
15
- end
16
- end