Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

upgrading hoptoad plugin install

  • Loading branch information...
commit 049c0e01e0aac051de4d42db1cc68473a8ca687b 1 parent c5afc6f
@rick authored
Showing with 5,951 additions and 0 deletions.
  1. +14 −0 vendor/plugins/hoptoad_notifier/.gitignore
  2. +3 −0  vendor/plugins/hoptoad_notifier/.yardopts
  3. +177 −0 vendor/plugins/hoptoad_notifier/CHANGELOG
  4. +25 −0 vendor/plugins/hoptoad_notifier/INSTALL
  5. +22 −0 vendor/plugins/hoptoad_notifier/MIT-LICENSE
  6. +382 −0 vendor/plugins/hoptoad_notifier/README.rdoc
  7. +217 −0 vendor/plugins/hoptoad_notifier/Rakefile
  8. +9 −0 vendor/plugins/hoptoad_notifier/SUPPORTED_RAILS_VERSIONS
  9. +8 −0 vendor/plugins/hoptoad_notifier/TESTING.rdoc
  10. +23 −0 vendor/plugins/hoptoad_notifier/features/metal.feature
  11. +27 −0 vendor/plugins/hoptoad_notifier/features/rack.feature
  12. +196 −0 vendor/plugins/hoptoad_notifier/features/rails.feature
  13. +33 −0 vendor/plugins/hoptoad_notifier/features/sinatra.feature
  14. +10 −0 vendor/plugins/hoptoad_notifier/features/step_definitions/file_steps.rb
  15. +10 −0 vendor/plugins/hoptoad_notifier/features/step_definitions/metal_steps.rb
  16. +20 −0 vendor/plugins/hoptoad_notifier/features/step_definitions/rack_steps.rb
  17. +353 −0 vendor/plugins/hoptoad_notifier/features/step_definitions/rails_application_steps.rb
  18. +18 −0 vendor/plugins/hoptoad_notifier/features/support/env.rb
  19. +7 −0 vendor/plugins/hoptoad_notifier/features/support/hoptoad_shim.rb.template
  20. +24 −0 vendor/plugins/hoptoad_notifier/features/support/matchers.rb
  21. +77 −0 vendor/plugins/hoptoad_notifier/features/support/rails.rb
  22. +92 −0 vendor/plugins/hoptoad_notifier/features/support/terminal.rb
  23. +63 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/hoptoad_generator.rb
  24. +34 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/lib/insert_commands.rb
  25. +24 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/lib/rake_commands.rb
  26. +6 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/capistrano_hook.rb
  27. +25 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/hoptoad_notifier_tasks.rake
  28. +6 −0 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/initializer.rb
  29. +32 −0 vendor/plugins/hoptoad_notifier/ginger_scenarios.rb
  30. +1 −0  vendor/plugins/hoptoad_notifier/install.rb
  31. +148 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier.rb
  32. +99 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/backtrace.rb
  33. +20 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/capistrano.rb
  34. +232 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/configuration.rb
  35. +327 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/notice.rb
  36. +40 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rack.rb
  37. +37 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rails.rb
  38. +29 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rails/action_controller_catcher.rb
  39. +60 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rails/controller_methods.rb
  40. +33 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rails/error_lookup.rb
  41. +90 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/rails3_tasks.rb
  42. +23 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/railtie.rb
  43. +63 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/sender.rb
  44. +97 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/tasks.rb
  45. +3 −0  vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/version.rb
  46. +44 −0 vendor/plugins/hoptoad_notifier/lib/hoptoad_tasks.rb
  47. +69 −0 vendor/plugins/hoptoad_notifier/lib/rails/generators/hoptoad/hoptoad_generator.rb
  48. +91 −0 vendor/plugins/hoptoad_notifier/lib/templates/rescue.erb
  49. +1 −0  vendor/plugins/hoptoad_notifier/rails/init.rb
  50. +38 −0 vendor/plugins/hoptoad_notifier/script/integration_test.rb
  51. +118 −0 vendor/plugins/hoptoad_notifier/test/backtrace_test.rb
  52. +329 −0 vendor/plugins/hoptoad_notifier/test/catcher_test.rb
  53. +208 −0 vendor/plugins/hoptoad_notifier/test/configuration_test.rb
  54. +239 −0 vendor/plugins/hoptoad_notifier/test/helper.rb
  55. +76 −0 vendor/plugins/hoptoad_notifier/test/hoptoad_2_0.xsd
  56. +152 −0 vendor/plugins/hoptoad_notifier/test/hoptoad_tasks_test.rb
  57. +85 −0 vendor/plugins/hoptoad_notifier/test/logger_test.rb
  58. +447 −0 vendor/plugins/hoptoad_notifier/test/notice_test.rb
  59. +222 −0 vendor/plugins/hoptoad_notifier/test/notifier_test.rb
  60. +58 −0 vendor/plugins/hoptoad_notifier/test/rack_test.rb
  61. +36 −0 vendor/plugins/hoptoad_notifier/test/rails_initializer_test.rb
  62. +123 −0 vendor/plugins/hoptoad_notifier/test/sender_test.rb
  63. +1 −0  vendor/plugins/hoptoad_notifier/vendor/ginger/.gitignore
  64. +20 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/LICENCE
  65. +50 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/README.textile
  66. +57 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/Rakefile
  67. +42 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/bin/ginger
  68. +21 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/lib/ginger.rb
  69. +20 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/lib/ginger/configuration.rb
  70. +56 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/lib/ginger/kernel.rb
  71. +24 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/lib/ginger/scenario.rb
  72. +7 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/spec/ginger/configuration_spec.rb
  73. +7 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/spec/ginger/kernel_spec.rb
  74. +50 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/spec/ginger/scenario_spec.rb
  75. +14 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/spec/ginger_spec.rb
  76. +7 −0 vendor/plugins/hoptoad_notifier/vendor/ginger/spec/spec_helper.rb
View
14 vendor/plugins/hoptoad_notifier/.gitignore
@@ -0,0 +1,14 @@
+log/*
+tmp
+db/schema.rb
+db/*.sqlite3
+public/system
+*.swp
+*.DS_Store
+coverage/*
+rdoc/
+tags
+.yardoc
+doc
+pkg
+*.gemspec
View
3  vendor/plugins/hoptoad_notifier/.yardopts
@@ -0,0 +1,3 @@
+-
+TESTING.rdoc
+MIT-LICENSE
View
177 vendor/plugins/hoptoad_notifier/CHANGELOG
@@ -0,0 +1,177 @@
+Version 2.3.2 - 2010-07-06
+===============================================================================
+
+Josh Clayton(1):
+ Handle instances when Rack's action_dispach.parameter_filter is nil
+
+
+Version 2.3.1 - 2010-07-02
+===============================================================================
+
+Jason Morrison (2):
+ Use the Rails 3 params filters when available
+ Filter session hash using Hoptoad config.params_filters, in addition to params
+
+
+Version 2.3.0 - 2010-06-24
+===============================================================================
+
+Jason Morrison (5):
+ Add integration test for rails 3.0.0.beta4
+ Added feature: Support the Heroku addon in the generator
+ Add --heroku flag to generator to support ENV['HOPTOAD_API_KEY']
+ Reflect a copy change in rails.feature for --heroku generator flag
+ Support the proxy configuration options when notifying Hoptoad of a deploy (hat tip @gudleik)
+
+
+Version 2.2.6 - 2010-06-02
+===============================================================================
+
+Jason Morrison (1):
+ For Rails 3, just use the Rack middleware instead of specifying a location to insert_after
+
+
+Version 2.2.5 - 2010-06-02
+===============================================================================
+
+Jason Morrison (1):
+ Add documentation for Rails 3.x installation
+
+
+Version 2.2.4 - 2010-06-02
+===============================================================================
+
+Jason Morrison (1):
+ Add a note to README about removing the explicit Catcher #include in ApplicationController
+
+
+Version 2.2.3 - 2010-06-02
+===============================================================================
+
+Summary: Fixed a variety of issues for Rails 3.0.0.beta3,
+ Fixed a bug when using Vlad to deploy instead of Capistrano
+ Give better error output when gem is not installed
+
+Chad Pytel (2):
+ revise gem unpack instructions step
+ Merge branch 'master' of github.com:thoughtbot/hoptoad_notifier
+
+Dan Lawless (1):
+ don't append capistrano details to config.deploy.rb when target app uses Vlad
+
+Jason Morrison (7):
+ LH-556 Clarify sending ENV environment variables
+ Starting to add features for Rails 3
+ Make rails rake tasks depend on gem-making tasks
+ Start to get Rails 3 features to pass
+ require fileutils to reflect rubygems 1.3.6 change
+ Support ENV['CUCUMBER_FORMAT'] in rails cucumber tasks for testing
+ Fix the initializer syntax in the Rails 3 Railtie
+
+Joe Ferris (11):
+ Got the generator running and a request dispatched to the test endpoint
+ Fixed logging in hoptoad:test rake task
+ Separated Rails 2 and 3 entry
+ Support bundler
+ Rails 3 generator works with an existing api key
+ Extract request info from rack env
+ Detect presence of the plugin
+ Added a capistrano hook for Rails 3
+ Fixed rack/sinatra being broken without active_support
+ Fixes for earlier versions of Rails
+ Fixed Rails 3 generator not to append cap hooks for vlad deploys
+
+Josh Kalderimis (7):
+ updated railtie to work with the new rails 3 middleware api
+ railtie_name is deprecated
+ updated app_middleware call to use string version as to make sure constant is loaded
+ moved generator using the new rails 3 convention
+ update path to template for Rails 3 generator
+ correction to referencing of the rails application in rails3_tasks
+ add environment_name and project_root back to rails 3 railtie
+
+Joshua Nichols (1):
+ Handle gem not being installed more gracefully.
+
+
+Version 2.2.2 - 2010-03-10
+===============================================================================
+
+Chad Pytel (1):
+ document proxy support
+
+Joe Ferris (8):
+ Added upgrade instructions to the README
+ Give a clearer error message when generating a Rails app fails
+ Fail loudly when a gem can't be vendored
+ Debugging rubygems issues
+ Explicitly specify the gem paths
+ Less noisy
+ Restore gem path after vendoring
+ Fixed a typo
+
+Jon Yurek (1):
+ Added notice about removing hoptoad rake tasks to upgrade gem
+
+Mike Burns (1):
+ Remove stray file with notes in it
+
+
+Version 2.2.1 - 2010-03-10
+===============================================================================
+
+Jason Morrison (3):
+ LH-629 Ensure notifier is not considered a framework gem
+ Removing things-the-generator-must-do file
+ Add rake cucumber:wip:rails* tasks for work-in-progress features
+
+
+Version 2.2.0 - 2010-02-18
+===============================================================================
+
+Bumping the version from 2.1.4 to 2.2.0 since adding Rack support warrants a minor version.
+
+Jason Morrison (1):
+ Stringify array elements when making assertions about Notice XML for 1.9 compatibility
+
+
+Version 2.1.4 - 2010-02-12
+===============================================================================
+
+Chad Pytel (2):
+ add more info to README for 1.2.6
+ fix gem unpack line for 1.2.6
+
+Jason Morrison (2):
+ Adding additional instructions for Rails 1.2.6
+ Typesetting in README.rdoc
+
+Joe Ferris (11):
+ Separating Rails functionality out more
+ Initial Rack middleware
+ Extract request info from rack env
+ Added integration tests for rescuing
+ Fixed reporting of Rails version
+ Small refactoring
+ Automatically add Rack middleware for Rails apps that support it (catches exceptions from Metal)
+ Added an integration test and docs for rack apps
+ Added integration/readme coverage of Sinatra apps
+ Added docs to HoptoadNotifier::Rack
+ Require rack in tests for older versions of Rails; use active_support instead of activesupport
+
+Nick Quaranto (3):
+ Fixing the capistrano hook bit in the readme
+ Adding changeling:minor and changeling:patch to automate notifier releases
+ Adding rake changeling:push
+
+
+
+
+
+
+
+
+
+
+
+
View
25 vendor/plugins/hoptoad_notifier/INSTALL
@@ -0,0 +1,25 @@
+=== Configuration
+
+You should have something like this in config/initializers/hoptoad.rb.
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ end
+
+(Please note that this configuration should be in a global configuration, and
+is *not* environment-specific. Hoptoad is smart enough to know what errors are
+caused by what environments, so your staging errors don't get mixed in with
+your production errors.)
+
+You can test that Hoptoad is working in your production environment by using
+this rake task (from RAILS_ROOT):
+
+ rake hoptoad:test
+
+If everything is configured properly, that task will send a notice to Hoptoad
+which will be visible immediately.
+
+NOTE FOR RAILS 1.2.* USERS:
+
+You will need to copy the hoptoad_notifier_tasks.rake file into your
+RAILS_ROOT/lib/tasks directory in order for the rake hoptoad:test task to work.
View
22 vendor/plugins/hoptoad_notifier/MIT-LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2007, Tammer Saleh, Thoughtbot, Inc.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
View
382 vendor/plugins/hoptoad_notifier/README.rdoc
@@ -0,0 +1,382 @@
+= HoptoadNotifier
+
+This is the notifier gem for integrating apps with Hoptoad.
+
+When an uncaught exception occurs, HoptoadNotifier will POST the relevant data
+to the Hoptoad server specified in your environment.
+
+== Help
+
+* {IRC}[irc://irc.freenode.net/thoughtbot]
+* {mailing list}[http://groups.google.com/group/hoptoad-notifier-dev]
+
+== Rails Installation
+
+=== Remove exception_notifier
+
+in your ApplicationController, REMOVE this line:
+
+ include ExceptionNotifiable
+
+In your config/environment* files, remove all references to ExceptionNotifier
+
+Remove the vendor/plugins/exception_notifier directory.
+
+=== Remove hoptoad_notifier plugin
+
+Remove the vendor/plugins/hoptoad_notifier directory before installing the gem, or run:
+
+ script/plugin remove hoptoad_notifier
+
+=== Rails 3.x
+
+Add the hoptoad_notifier gem to your Gemfile. In Gemfile:
+
+ gem 'hoptoad_notifier'
+
+Then from your project's RAILS_ROOT, run:
+
+ bundle install
+ script/rails generate hoptoad --api-key your_key_here
+
+That's it!
+
+=== Rails 2.x
+
+Add the hoptoad_notifier gem to your app. In config/environment.rb:
+
+ config.gem 'hoptoad_notifier'
+
+Then from your project's RAILS_ROOT, run:
+
+ rake gems:install
+ rake gems:unpack GEM=hoptoad_notifier
+ script/generate hoptoad --api-key your_key_here
+
+As always, if you choose not to vendor the hoptoad_notifier gem, make sure
+every server you deploy to has the gem installed or your application won't start.
+
+=== Rails 1.2.6
+
+Install the hoptoad_notifier gem:
+
+ gem install hoptoad_notifier
+
+Once installed, you should vendor the hoptoad_notifier gem:
+
+ mkdir vendor/gems
+ cd vendor/gems
+ gem unpack hoptoad_notifier
+
+And then add the following to the Rails::Initializer.run do |config|
+block in environment.rb so that the vendored gem is loaded.
+
+ # Add the vendor/gems/*/lib directories to the LOAD_PATH
+ config.load_paths += Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', '*', 'lib'))
+
+Next add something like this at the bottom of your config/environment.rb:
+
+ require 'hoptoad_notifier'
+ require 'hoptoad_notifier/rails'
+ HoptoadNotifier.configure do |config|
+ config.api_key = 'your_key_here'
+ end
+
+You will also need to copy the hoptoad_notifier_tasks.rake file into your
+RAILS_ROOT/lib/tasks directory in order for the rake hoptoad:test task to work:
+
+ cp vendor/gems/hoptoad_notifier-*/generators/hoptoad/templates/hoptoad_notifier_tasks.rake lib/tasks
+
+As always, if you choose not to vendor the hoptoad_notifier gem, make sure
+every server you deploy to has the gem installed or your application won't start.
+
+=== Upgrading From Earlier Versions of Hoptoad
+
+If you're currently using the plugin version (if you have a
+vendor/plugins/hoptoad_notifier directory, you are), you'll need to perform a
+few extra steps when upgrading to the gem version.
+
+Add the hoptoad_notifier gem to your app. In config/environment.rb:
+
+ config.gem 'hoptoad_notifier'
+
+Remove the plugin:
+
+ rm -rf vendor/plugins/hoptoad_notifier
+
+Make sure the following line DOES NOT appear in your ApplicationController file:
+
+ include HoptoadNotifier::Catcher
+
+If it does, remove it. The new catcher is automatically included by the gem
+version of Hoptoad.
+
+Before running the hoptoad generator, you need to find your project's API key.
+Log in to your account at hoptoadapp.com, and click on the "Projects" button.
+Then, find your project in the list, and click on its name. In the left-hand
+column, you'll see an "Edit this project" button. Click on that to get your
+project's API. (If you accidentally use your personal API auth_token, you won't
+be able to install the gem.)
+
+Then from your project's RAILS_ROOT, run:
+
+ rake gems:install
+ script/generate hoptoad --api-key your_key_here
+
+Once installed, you should vendor the hoptoad_notifier gem.
+
+ rake gems:unpack GEM=hoptoad_notifier
+
+As always, if you choose not to vendor the hoptoad_notifier gem, make sure
+every server you deploy to has the gem installed or your application won't
+start.
+
+== Upgrading from Earlier Versions of the Hoptoad Gem (with config.gem)
+
+If you're currently using the gem version of the hoptoad_notifier and have
+a version of Rails that uses config.gem (in the 2.x series), there is
+a step or two that you need to do to upgrade. First, you need to remove
+the old version of the gem from vendor/gems:
+
+ rm -rf vendor/gems/hoptoad_notifier-X.X.X
+
+Then you must remove the hoptoad_notifier_tasks.rake file from lib:
+
+ rm lib/tasks/hoptoad_notifier_tasks.rake
+
+You can them continue to install normally. If you don't remove the rake file,
+you will be unable to unpack this gem (Rails will think it's part of the
+framework).
+
+=== Testing it out
+
+You can test that Hoptoad is working in your production environment by using
+this rake task (from RAILS_ROOT):
+
+ rake hoptoad:test
+
+If everything is configured properly, that task will send a notice to Hoptoad
+which will be visible immediately.
+
+== Rack
+
+In order to use hoptoad_notifier in a non-Rails rack app, just load the
+hoptoad_notifier, configure your API key, and use the HoptoadNotifier::Rack
+middleware:
+
+ require 'rack'
+ require 'hoptoad_notifier'
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = 'my_api_key'
+ end
+
+ app = Rack::Builder.app do
+ use HoptoadNotifier::Rack
+ run lambda { |env| raise "Rack down" }
+ end
+
+== Sinatra
+
+Using hoptoad_notifier in a Sinatra app is just like a Rack app, but you have
+to disable Sinatra's error rescuing functionality:
+
+ require 'sinatra/base'
+ require 'hoptoad_notifier'
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = 'my_api_key'
+ end
+
+ class MyApp < Sinatra::Default
+ use HoptoadNotifier::Rack
+ enable :raise_errors
+
+ get "/" do
+ raise "Sinatra has left the building"
+ end
+ end
+
+== Usage
+
+For the most part, Hoptoad works for itself. Once you've included the notifier
+in your ApplicationController (which is now done automatically by the gem),
+all errors will be rescued by the #rescue_action_in_public provided by the gem.
+
+If you want to log arbitrary things which you've rescued yourself from a
+controller, you can do something like this:
+
+ ...
+ rescue => ex
+ notify_hoptoad(ex)
+ flash[:failure] = 'Encryptions could not be rerouted, try again.'
+ end
+ ...
+
+The #notify_hoptoad call will send the notice over to Hoptoad for later
+analysis. While in your controllers you use the notify_hoptoad method, anywhere
+else in your code, use HoptoadNotifier.notify.
+
+To perform custom error processing after Hoptoad has been notified, define the
+instance method #rescue_action_in_public_without_hoptoad(exception) in your
+controller.
+
+== Tracking deployments in Hoptoad
+
+Paying Hoptoad plans support the ability to track deployments of your application in Hoptoad.
+By notifying Hoptoad of your application deployments, all errors are resolved when a deploy occurs,
+so that you'll be notified again about any errors that reoccur after a deployment.
+
+Additionally, it's possible to review the errors in Hoptoad that occurred before and after a deploy.
+
+When Hoptoad is installed as a gem, you need to add
+
+ require 'hoptoad_notifier/capistrano'
+
+to your deploy.rb
+
+== Going beyond exceptions
+
+You can also pass a hash to notify_hoptoad method and store whatever you want,
+not just an exception. And you can also use it anywhere, not just in
+controllers:
+
+ begin
+ params = {
+ # params that you pass to a method that can throw an exception
+ }
+ my_unpredicable_method(params)
+ rescue => e
+ HoptoadNotifier.notify(
+ :error_class => "Special Error",
+ :error_message => "Special Error: #{e.message}",
+ :parameters => params
+ )
+ end
+
+While in your controllers you use the notify_hoptoad method, anywhere else in
+your code, use HoptoadNotifier.notify. Hoptoad will get all the information
+about the error itself. As for a hash, these are the keys you should pass:
+
+* :error_class - Use this to group similar errors together. When Hoptoad catches an exception it sends the class name of that exception object.
+* :error_message - This is the title of the error you see in the errors list. For exceptions it is "#{exception.class.name}: #{exception.message}"
+* :parameters - While there are several ways to send additional data to Hoptoad, passing a Hash as :parameters as in the example above is the most common use case. When Hoptoad catches an exception in a controller, the actual HTTP client request parameters are sent using this key.
+
+Hoptoad merges the hash you pass with these default options:
+
+ {
+ :api_key => HoptoadNotifier.api_key,
+ :error_message => 'Notification',
+ :backtrace => caller,
+ :parameters => {},
+ :session => {}
+ }
+
+You can override any of those parameters.
+
+=== Sending shell environment variables when "Going beyond exceptions"
+
+One common request we see is to send shell environment variables along with
+manual exception notification. We recommend sending them along with CGI data
+or Rack environment (:cgi_data or :rack_env keys, respectively.)
+
+See HoptoadNotifier::Notice#initialize in lib/hoptoad_notifier/notice.rb for
+more details.
+
+== Filtering
+
+You can specify a whitelist of errors, that Hoptoad will not report on. Use
+this feature when you are so apathetic to certain errors that you don't want
+them even logged.
+
+This filter will only be applied to automatic notifications, not manual
+notifications (when #notify is called directly).
+
+Hoptoad ignores the following exceptions by default:
+
+ ActiveRecord::RecordNotFound
+ ActionController::RoutingError
+ ActionController::InvalidAuthenticityToken
+ ActionController::UnknownAction
+ CGI::Session::CookieStore::TamperedWithCookie
+
+To ignore errors in addition to those, specify their names in your Hoptoad
+configuration block.
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ config.ignore << ActiveRecord::IgnoreThisError
+ end
+
+To ignore *only* certain errors (and override the defaults), use the
+#ignore_only attribute.
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ config.ignore_only = [ActiveRecord::IgnoreThisError]
+ end
+
+To ignore certain user agents, add in the #ignore_user_agent attribute as a
+string or regexp:
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ config.ignore_user_agent << /Ignored/
+ config.ignore_user_agent << 'IgnoredUserAgent'
+ end
+
+To ignore exceptions based on other conditions, use #ignore_by_filter:
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ config.ignore_by_filter do |exception_data|
+ true if exception_data[:error_class] == "RuntimeError"
+ end
+ end
+
+To replace sensitive information sent to the Hoptoad service with [FILTERED] use #params_filters:
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = '1234567890abcdef'
+ config.params_filters << "credit_card_number"
+ end
+
+Note that, when rescuing exceptions within an ActionController method,
+hoptoad_notifier will reuse filters specified by #filter_parameter_logging.
+
+== Testing
+
+When you run your tests, you might notice that the Hoptoad service is recording
+notices generated using #notify when you don't expect it to. You can
+use code like this in your test_helper.rb to redefine that method so those
+errors are not reported while running tests.
+
+ module HoptoadNotifier
+ def self.notify(thing)
+ # do nothing.
+ end
+ end
+
+== Proxy Support
+
+The notifier supports using a proxy, if your server is not able to directly reach the Hoptoad servers. To configure the proxy settings, added the following information to your Hoptoad configuration block.
+
+ HoptoadNotifier.configure do |config|
+ config.proxy_host = ...
+ config.proxy_port = ...
+ config.proxy_user = ...
+ config.proxy_pass = ...
+
+== Supported Rails versions
+
+See SUPPORTED_RAILS_VERSIONS for a list of official supported versions of
+Rails.
+
+Please open up a support ticket on Tender ( http://help.hoptoadapp.com ) if
+you're using a version of Rails that is not listed above and the notifier is
+not working properly.
+
+== Thanks
+
+Thanks to Eugene Bolshakov for the excellent write-up on GOING BEYOND
+EXCEPTIONS, which we have included above.
View
217 vendor/plugins/hoptoad_notifier/Rakefile
@@ -0,0 +1,217 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+require 'rake/gempackagetask'
+require 'cucumber/rake/task'
+
+desc 'Default: run unit tests.'
+task :default => [:test, :cucumber]
+
+desc 'Test the hoptoad_notifier gem.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Run ginger tests'
+task :ginger do
+ $LOAD_PATH << File.join(*%w[vendor ginger lib])
+ ARGV.clear
+ ARGV << 'test'
+ load File.join(*%w[vendor ginger bin ginger])
+end
+
+namespace :changeling do
+ desc "Bumps the version by a minor or patch version, depending on what was passed in."
+ task :bump, :part do |t, args|
+ # Thanks, Jeweler!
+ if HoptoadNotifier::VERSION =~ /^(\d+)\.(\d+)\.(\d+)(?:\.(.*?))?$/
+ major = $1.to_i
+ minor = $2.to_i
+ patch = $3.to_i
+ build = $4
+ else
+ abort
+ end
+
+ case args[:part]
+ when /minor/
+ minor += 1
+ patch = 0
+ when /patch/
+ patch += 1
+ else
+ abort
+ end
+
+ version = [major, minor, patch, build].compact.join('.')
+
+ File.open(File.join("lib", "hoptoad_notifier", "version.rb"), "w") do |f|
+ f.write <<EOF
+module HoptoadNotifier
+ VERSION = "#{version}".freeze
+end
+EOF
+ end
+ end
+
+ desc "Writes out the new CHANGELOG and prepares the release"
+ task :change do
+ load 'lib/hoptoad_notifier/version.rb'
+ file = "CHANGELOG"
+ old = File.read(file)
+ version = HoptoadNotifier::VERSION
+ message = "Bumping to version #{version}"
+
+ File.open(file, "w") do |f|
+ f.write <<EOF
+Version #{version} - #{Date.today}
+===============================================================================
+
+#{`git log $(git tag | tail -1)..HEAD | git shortlog`}
+#{old}
+EOF
+ end
+
+ exec ["#{ENV["EDITOR"]} #{file}",
+ "git commit -aqm '#{message}'",
+ "git tag -a -m '#{message}' v#{version}",
+ "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(' && ')
+ end
+
+ desc "Bump by a minor version (1.2.3 => 1.3.0)"
+ task :minor do |t|
+ Rake::Task['changeling:bump'].invoke(t.name)
+ Rake::Task['changeling:change'].invoke
+ end
+
+ desc "Bump by a patch version, (1.2.3 => 1.2.4)"
+ task :patch do |t|
+ Rake::Task['changeling:bump'].invoke(t.name)
+ Rake::Task['changeling:change'].invoke
+ end
+
+ desc "Push the latest version and tags"
+ task :push do |t|
+ system("git push origin master")
+ system("git push origin $(git tag | tail -1)")
+ end
+end
+
+begin
+ require 'yard'
+ YARD::Rake::YardocTask.new do |t|
+ t.files = ['lib/**/*.rb', 'TESTING.rdoc']
+ end
+rescue LoadError
+end
+
+GEM_ROOT = File.dirname(__FILE__).freeze
+VERSION_FILE = File.join(GEM_ROOT, 'lib', 'hoptoad_notifier', 'version')
+
+require VERSION_FILE
+
+gemspec = Gem::Specification.new do |s|
+ s.name = %q{hoptoad_notifier}
+ s.version = HoptoadNotifier::VERSION
+ s.summary = %q{Send your application errors to our hosted service and reclaim your inbox.}
+
+ s.files = FileList['[A-Z]*', 'generators/**/*.*', 'lib/**/*.rb',
+ 'test/**/*.rb', 'rails/**/*.rb', 'script/*',
+ 'lib/templates/*.erb']
+ s.require_path = 'lib'
+ s.test_files = Dir[*['test/**/*_test.rb']]
+
+ s.has_rdoc = true
+ s.extra_rdoc_files = ["README.rdoc"]
+ s.rdoc_options = ['--line-numbers', "--main", "README.rdoc"]
+
+ s.add_runtime_dependency("activesupport")
+ s.add_development_dependency("activerecord")
+ s.add_development_dependency("actionpack")
+ s.add_development_dependency("jferris-mocha")
+ s.add_development_dependency("nokogiri")
+ s.add_development_dependency("shoulda")
+
+ s.authors = ["thoughtbot, inc"]
+ s.email = %q{support@hoptoadapp.com}
+ s.homepage = "http://www.hoptoadapp.com"
+
+ s.platform = Gem::Platform::RUBY
+end
+
+Rake::GemPackageTask.new gemspec do |pkg|
+ pkg.need_tar = true
+ pkg.need_zip = true
+end
+
+desc "Clean files generated by rake tasks"
+task :clobber => [:clobber_rdoc, :clobber_package]
+
+desc "Generate a gemspec file"
+task :gemspec do
+ File.open("#{gemspec.name}.gemspec", 'w') do |f|
+ f.write gemspec.to_ruby
+ end
+end
+
+LOCAL_GEM_ROOT = File.join(GEM_ROOT, 'tmp', 'local_gems').freeze
+RAILS_VERSIONS = IO.read('SUPPORTED_RAILS_VERSIONS').strip.split("\n")
+LOCAL_GEMS = [['sham_rack', nil], ['capistrano', nil], ['sqlite3-ruby', nil], ['sinatra', nil]] +
+ RAILS_VERSIONS.collect { |version| ['rails', version] }
+
+task :vendor_test_gems do
+ old_gem_path = ENV['GEM_PATH']
+ old_gem_home = ENV['GEM_HOME']
+ ENV['GEM_PATH'] = LOCAL_GEM_ROOT
+ ENV['GEM_HOME'] = LOCAL_GEM_ROOT
+ LOCAL_GEMS.each do |gem_name, version|
+ gem_file_pattern = [gem_name, version || '*'].compact.join('-')
+ version_option = version ? "-v #{version}" : ''
+ pattern = File.join(LOCAL_GEM_ROOT, 'gems', "#{gem_file_pattern}")
+ existing = Dir.glob(pattern).first
+ unless existing
+ command = "gem install -i #{LOCAL_GEM_ROOT} --no-ri --no-rdoc --backtrace #{version_option} #{gem_name}"
+ puts "Vendoring #{gem_file_pattern}..."
+ unless system("#{command} 2>&1")
+ puts "Command failed: #{command}"
+ exit(1)
+ end
+ end
+ end
+ ENV['GEM_PATH'] = old_gem_path
+ ENV['GEM_HOME'] = old_gem_home
+end
+
+Cucumber::Rake::Task.new(:cucumber) do |t|
+ t.fork = true
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+end
+
+task :cucumber => [:gemspec, :vendor_test_gems]
+
+def define_rails_cucumber_tasks(additional_cucumber_args = '')
+ namespace :rails do
+ RAILS_VERSIONS.each do |version|
+ desc "Test integration of the gem with Rails #{version}"
+ task version => [:gemspec, :vendor_test_gems] do
+ puts "Testing Rails #{version}"
+ ENV['RAILS_VERSION'] = version
+ system("cucumber --format #{ENV['CUCUMBER_FORMAT'] || 'progress'} #{additional_cucumber_args} features/rails.feature")
+ end
+ end
+
+ desc "Test integration of the gem with all Rails versions"
+ task :all => RAILS_VERSIONS
+ end
+end
+
+namespace :cucumber do
+ namespace :wip do
+ define_rails_cucumber_tasks('--tags @wip')
+ end
+
+ define_rails_cucumber_tasks
+end
+
View
9 vendor/plugins/hoptoad_notifier/SUPPORTED_RAILS_VERSIONS
@@ -0,0 +1,9 @@
+1.2.6
+2.0.2
+2.1.0
+2.1.2
+2.2.2
+2.3.2
+2.3.4
+2.3.5
+3.0.0.beta4
View
8 vendor/plugins/hoptoad_notifier/TESTING.rdoc
@@ -0,0 +1,8 @@
+= For Maintainers:
+
+When developing the Hoptoad Notifier, be sure to use the integration test
+against an existing project on staging before pushing to master.
+
++./script/integration_test.rb <test project's api key> <staging server hostname>+
+
++./script/integration_test.rb <test project's api key> <staging server hostname> secure+
View
23 vendor/plugins/hoptoad_notifier/features/metal.feature
@@ -0,0 +1,23 @@
+Feature: Rescue errors in Rails middleware
+
+ Background:
+ Given I have built and installed the "hoptoad_notifier" gem
+ And I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run "script/generate hoptoad -k myapikey"
+
+ Scenario: Rescue an exception in the dispatcher
+ When I define a Metal endpoint called "Exploder":
+ """
+ def self.call(env)
+ raise "Explode"
+ end
+ """
+ When I perform a request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | error message | RuntimeError: Explode |
+ | error class | RuntimeError |
+ | parameters | param: value |
+ | url | http://example.com:123/test/index?param=value |
+
View
27 vendor/plugins/hoptoad_notifier/features/rack.feature
@@ -0,0 +1,27 @@
+Feature: Use the notifier in a plain Rack app
+
+ Background:
+ Given I have built and installed the "hoptoad_notifier" gem
+
+ Scenario: Rescue and exception in a Rack app
+ Given the following Rack app:
+ """
+ require 'rack'
+ require 'hoptoad_notifier'
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = 'my_api_key'
+ end
+
+ app = Rack::Builder.app do
+ use HoptoadNotifier::Rack
+ run lambda { |env| raise "Rack down" }
+ end
+ """
+ When I perform a Rack request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | error message | RuntimeError: Rack down |
+ | error class | RuntimeError |
+ | parameters | param: value |
+ | url | http://example.com:123/test/index?param=value |
+
View
196 vendor/plugins/hoptoad_notifier/features/rails.feature
@@ -0,0 +1,196 @@
+Feature: Install the Gem in a Rails application
+
+ Background:
+ Given I have built and installed the "hoptoad_notifier" gem
+
+ Scenario: Use the gem without vendoring the gem in a Rails application
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ Then the command should have run successfully
+ And I should receive a Hoptoad notification
+ And I should see the Rails version
+
+ Scenario: vendor the gem and uninstall
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I unpack the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ Then the command should have run successfully
+ When I uninstall the "hoptoad_notifier" gem
+ And I install cached gems
+ And I run "rake hoptoad:test"
+ Then I should see "** [Hoptoad] Success: Net::HTTPOK"
+ And I should receive two Hoptoad notifications
+
+ Scenario: Configure the notifier by hand
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure the notifier to use "myapikey" as an API key
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with ""
+ Then I should receive a Hoptoad notification
+
+ Scenario: Try to install without an api key
+ When I generate a new Rails application
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with ""
+ Then I should see "Must pass --api-key or --heroku or create config/initializers/hoptoad.rb"
+
+ Scenario: Configure and deploy using only installed gem
+ When I generate a new Rails application
+ And I run "capify ."
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ And I run "cap -T"
+ Then I should see "deploy:notify_hoptoad"
+
+ Scenario: Configure and deploy using only vendored gem
+ When I generate a new Rails application
+ And I run "capify ."
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I unpack the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ And I uninstall the "hoptoad_notifier" gem
+ And I install cached gems
+ And I run "cap -T"
+ Then I should see "deploy:notify_hoptoad"
+
+ Scenario: Try to install when the hoptoad_notifier plugin still exists
+ When I generate a new Rails application
+ And I install the "hoptoad_notifier" plugin
+ And I configure the Hoptoad shim
+ And I configure the notifier to use "myapikey" as an API key
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with ""
+ Then I should see "You must first remove the hoptoad_notifier plugin. Please run: script/plugin remove hoptoad_notifier"
+
+ Scenario: Rescue an exception in a controller
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ And I define a response for "TestController#index":
+ """
+ session[:value] = "test"
+ raise RuntimeError, "some message"
+ """
+ And I route "/test/index" to "test#index"
+ And I perform a request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | component | test |
+ | action | index |
+ | error message | RuntimeError: some message |
+ | error class | RuntimeError |
+ | session | value: test |
+ | parameters | param: value |
+ | url | http://example.com:123/test/index?param=value |
+
+ Scenario: The gem should not be considered a framework gem
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ And I run "rake gems"
+ Then I should see that "hoptoad_notifier" is not considered a framework gem
+
+ Scenario: The app uses Vlad instead of Capistrano
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run "touch config/deploy.rb"
+ And I run "rm Capfile"
+ And I run the hoptoad generator with "-k myapikey"
+ Then "config/deploy.rb" should not contain "capistrano"
+
+ Scenario: Support the Heroku addon in the generator
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure the Heroku rake shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I set the environment variable "HOPTOAD_API_KEY" to "myapikey"
+ And I run the hoptoad generator with "--heroku"
+ Then the command should have run successfully
+ And I should receive a Hoptoad notification
+ And I should see the Rails version
+ And my Hoptoad configuration should contain the following line:
+ """
+ config.api_key = ENV['HOPTOAD_API_KEY']
+ """
+
+ Scenario: Filtering parameters in a controller
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ When I configure the notifier to use the following configuration lines:
+ """
+ config.api_key = "myapikey"
+ config.params_filters << "credit_card_number"
+ """
+ And I define a response for "TestController#index":
+ """
+ params[:credit_card_number] = "red23"
+ raise RuntimeError, "some message"
+ """
+ And I route "/test/index" to "test#index"
+ And I perform a request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | component | test |
+ | action | index |
+ | error message | RuntimeError: some message |
+ | error class | RuntimeError |
+ | parameters | credit_card_number: [FILTERED] |
+ | url | http://example.com:123/test/index?param=value |
+
+ Scenario: Filtering session in a controller
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ When I configure the notifier to use the following configuration lines:
+ """
+ config.api_key = "myapikey"
+ config.params_filters << "secret"
+ """
+ And I define a response for "TestController#index":
+ """
+ session["secret"] = "blue42"
+ raise RuntimeError, "some message"
+ """
+ And I route "/test/index" to "test#index"
+ And I perform a request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | component | test |
+ | action | index |
+ | error message | RuntimeError: some message |
+ | error class | RuntimeError |
+ | session | secret: [FILTERED] |
+ | url | http://example.com:123/test/index?param=value |
+
+ Scenario: Filtering session and params based on Rails parameter filters
+ When I generate a new Rails application
+ And I configure the Hoptoad shim
+ And I configure my application to require the "hoptoad_notifier" gem
+ And I run the hoptoad generator with "-k myapikey"
+ And I configure the application to filter parameter "secret"
+ And I define a response for "TestController#index":
+ """
+ params["secret"] = "red23"
+ session["secret"] = "blue42"
+ raise RuntimeError, "some message"
+ """
+ And I route "/test/index" to "test#index"
+ And I perform a request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | component | test |
+ | action | index |
+ | error message | RuntimeError: some message |
+ | error class | RuntimeError |
+ | params | secret: [FILTERED] |
+ | session | secret: [FILTERED] |
+ | url | http://example.com:123/test/index?param=value |
View
33 vendor/plugins/hoptoad_notifier/features/sinatra.feature
@@ -0,0 +1,33 @@
+Feature: Use the notifier in a Sinatra app
+
+ Background:
+ Given I have built and installed the "hoptoad_notifier" gem
+
+ Scenario: Rescue an exception in a Sinatra app
+ Given the following Rack app:
+ """
+ require 'sinatra/base'
+ require 'hoptoad_notifier'
+
+ HoptoadNotifier.configure do |config|
+ config.api_key = 'my_api_key'
+ end
+
+ class FontaneApp < Sinatra::Default
+ use HoptoadNotifier::Rack
+ enable :raise_errors
+
+ get "/test/index" do
+ raise "Sinatra has left the building"
+ end
+ end
+
+ app = FontaneApp
+ """
+ When I perform a Rack request to "http://example.com:123/test/index?param=value"
+ Then I should receive the following Hoptoad notification:
+ | error message | RuntimeError: Sinatra has left the building |
+ | error class | RuntimeError |
+ | parameters | param: value |
+ | url | http://example.com:123/test/index?param=value |
+
View
10 vendor/plugins/hoptoad_notifier/features/step_definitions/file_steps.rb
@@ -0,0 +1,10 @@
+Then /^"([^\"]*)" should not contain text of "([^\"]*)"$/ do |target_file, contents_file|
+ notifier_root = File.join(File.dirname(__FILE__), '..', '..')
+ full_path_contents = File.join(notifier_root, contents_file)
+ contents_text = File.open(full_path_contents).read
+
+ full_path_target = File.join(RAILS_ROOT, target_file)
+ target_text = File.open(full_path_target).read
+
+ target_text.should_not include(contents_text)
+end
View
10 vendor/plugins/hoptoad_notifier/features/step_definitions/metal_steps.rb
@@ -0,0 +1,10 @@
+When /^I define a Metal endpoint called "([^\"]*)":$/ do |class_name, definition|
+ FileUtils.mkdir_p(File.join(RAILS_ROOT, 'app', 'metal'))
+ file_name = File.join(RAILS_ROOT, 'app', 'metal', "#{class_name.underscore}.rb")
+ File.open(file_name, "w") do |file|
+ file.puts "class #{class_name}"
+ file.puts definition
+ file.puts "end"
+ end
+end
+
View
20 vendor/plugins/hoptoad_notifier/features/step_definitions/rack_steps.rb
@@ -0,0 +1,20 @@
+Given /^the following Rack app:$/ do |definition|
+ File.open(RACK_FILE, 'w') { |file| file.write(definition) }
+end
+
+When /^I perform a Rack request to "([^\"]*)"$/ do |url|
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'hoptoad_shim.rb.template')
+ request_file = File.join(TEMP_DIR, 'rack_request.rb')
+ File.open(request_file, 'w') do |file|
+ file.puts "require 'rubygems'"
+ file.puts IO.read(shim_file)
+ file.puts IO.read(RACK_FILE)
+ file.puts "env = Rack::MockRequest.env_for(#{url.inspect})"
+ file.puts "status, headers, body = app.call(env)"
+ file.puts %{puts "HTTP \#{status}"}
+ file.puts %{headers.each { |key, value| puts "\#{key}: \#{value}"}}
+ file.puts "body.each { |part| print part }"
+ end
+ @terminal.run("ruby #{request_file}")
+end
+
View
353 vendor/plugins/hoptoad_notifier/features/step_definitions/rails_application_steps.rb
@@ -0,0 +1,353 @@
+require 'uri'
+require 'active_support/core_ext/string/inflections'
+
+When /^I generate a new Rails application$/ do
+ @terminal.cd(TEMP_DIR)
+ version_string = ENV['RAILS_VERSION']
+
+ rails3 = version_string =~ /^3/
+
+ if rails3
+ rails_create_command = 'new'
+ else
+ rails_create_command = ''
+ end
+
+ load_rails = <<-RUBY
+ gem 'rails', '#{version_string}'; \
+ load Gem.bin_path('rails', 'rails', '#{version_string}')
+ RUBY
+
+ @terminal.run(%{ruby -rubygems -e "#{load_rails.strip!}" #{rails_create_command} rails_root})
+ if rails_root_exists?
+ @terminal.echo("Generated a Rails #{version_string} application")
+ else
+ raise "Unable to generate a Rails application:\n#{@terminal.output}"
+ end
+end
+
+When /^I run the hoptoad generator with "([^\"]*)"$/ do |generator_args|
+ if rails3?
+ When %{I run "script/rails generate hoptoad #{generator_args}"}
+ else
+ When %{I run "script/generate hoptoad #{generator_args}"}
+ end
+end
+
+Given /^I have installed the "([^\"]*)" gem$/ do |gem_name|
+ @terminal.install_gem(gem_name)
+end
+
+Given /^I have built and installed the "([^\"]*)" gem$/ do |gem_name|
+ @terminal.build_and_install_gem(File.join(PROJECT_ROOT, "#{gem_name}.gemspec"))
+end
+
+When /^I configure my application to require the "([^\"]*)" gem$/ do |gem_name|
+ if rails_manages_gems?
+ config_gem(gem_name)
+ elsif bundler_manages_gems?
+ bundle_gem(gem_name)
+ else
+ File.open(environment_path, 'a') do |file|
+ file.puts
+ file.puts("require 'hoptoad_notifier'")
+ file.puts("require 'hoptoad_notifier/rails'")
+ end
+
+ unless rails_finds_generators_in_gems?
+ FileUtils.cp_r(File.join(PROJECT_ROOT, 'generators'), File.join(RAILS_ROOT, 'lib'))
+ end
+ end
+end
+
+When /^I run "([^\"]*)"$/ do |command|
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run(command)
+end
+
+Then /^I should receive a Hoptoad notification$/ do
+ Then %{I should see "[Hoptoad] Success: Net::HTTPOK"}
+end
+
+Then /^I should receive two Hoptoad notifications$/ do
+ @terminal.output.scan(/\[Hoptoad\] Success: Net::HTTPOK/).size.should == 2
+end
+
+When /^I configure the Hoptoad shim$/ do
+ if bundler_manages_gems?
+ bundle_gem("sham_rack")
+ end
+
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'hoptoad_shim.rb.template')
+ if rails_supports_initializers?
+ target = File.join(RAILS_ROOT, 'config', 'initializers', 'hoptoad_shim.rb')
+ FileUtils.cp(shim_file, target)
+ else
+ File.open(environment_path, 'a') do |file|
+ file.puts
+ file.write IO.read(shim_file)
+ end
+ end
+end
+
+When /^I configure the notifier to use "([^\"]*)" as an API key$/ do |api_key|
+ steps %{
+ When I configure the notifier to use the following configuration lines:
+ """
+ config.api_key = #{api_key.inspect}
+ """
+ }
+end
+
+When /^I configure the notifier to use the following configuration lines:$/ do |configuration_lines|
+ if rails_manages_gems?
+ requires = ''
+ else
+ requires = "require 'hoptoad_notifier'"
+ end
+
+ initializer_code = <<-EOF
+ #{requires}
+ HoptoadNotifier.configure do |config|
+ #{configuration_lines}
+ end
+ EOF
+
+ if rails_supports_initializers?
+ File.open(rails_initializer_file, 'w') { |file| file.write(initializer_code) }
+ else
+ File.open(environment_path, 'a') do |file|
+ file.puts
+ file.puts initializer_code
+ end
+ end
+
+end
+
+def rails_initializer_file
+ File.join(RAILS_ROOT, 'config', 'initializers', 'hoptoad.rb')
+end
+
+def rails_non_initializer_hoptoad_config_file
+ File.join(RAILS_ROOT, 'config', 'hoptoad.rb')
+end
+
+Then /^I should see "([^\"]*)"$/ do |expected_text|
+ unless @terminal.output.include?(expected_text)
+ raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}")
+ end
+end
+
+Then /^I should not see "([^\"]*)"$/ do |unexpected_text|
+ if @terminal.output.include?(unexpected_text)
+ raise("Got terminal output:\n#{@terminal.output}\n\nDid not expect the following output:\n#{unexpected_text}")
+ end
+end
+
+When /^I uninstall the "([^\"]*)" gem$/ do |gem_name|
+ @terminal.uninstall_gem(gem_name)
+end
+
+When /^I unpack the "([^\"]*)" gem$/ do |gem_name|
+ if bundler_manages_gems?
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run("bundle pack")
+ elsif rails_manages_gems?
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run("rake gems:unpack GEM=#{gem_name}")
+ else
+ vendor_dir = File.join(RAILS_ROOT, 'vendor', 'gems')
+ FileUtils.mkdir_p(vendor_dir)
+ @terminal.cd(vendor_dir)
+ @terminal.run("gem unpack #{gem_name}")
+ gem_path =
+ Dir.glob(File.join(RAILS_ROOT, 'vendor', 'gems', "#{gem_name}-*", 'lib')).first
+ File.open(environment_path, 'a') do |file|
+ file.puts
+ file.puts("$: << #{gem_path.inspect}")
+ end
+ end
+end
+
+When /^I install cached gems$/ do
+ if bundler_manages_gems?
+ When %{I run "bundle install"}
+ end
+end
+
+When /^I install the "([^\"]*)" plugin$/ do |plugin_name|
+ FileUtils.mkdir_p("#{RAILS_ROOT}/vendor/plugins/#{plugin_name}")
+end
+
+When /^I define a response for "([^\"]*)":$/ do |controller_and_action, definition|
+ controller_class_name, action = controller_and_action.split('#')
+ controller_name = controller_class_name.underscore
+ controller_file_name = File.join(RAILS_ROOT, 'app', 'controllers', "#{controller_name}.rb")
+ File.open(controller_file_name, "w") do |file|
+ file.puts "class #{controller_class_name} < ApplicationController"
+ file.puts "def consider_all_requests_local; false; end"
+ file.puts "def local_request?; false; end"
+ file.puts "def #{action}"
+ file.puts definition
+ file.puts "end"
+ file.puts "end"
+ end
+end
+
+When /^I perform a request to "([^\"]*)"$/ do |uri|
+ if rails_uses_rack?
+ request_script = <<-SCRIPT
+ require 'config/environment'
+ env = Rack::MockRequest.env_for(#{uri.inspect})
+ RailsRoot::Application.call(env)
+ SCRIPT
+ File.open(File.join(RAILS_ROOT, 'request.rb'), 'w') { |file| file.write(request_script) }
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run("./script/rails runner -e production request.rb")
+ else
+ uri = URI.parse(uri)
+ request_script = <<-SCRIPT
+ require 'cgi'
+ class CGIWrapper < CGI
+ def initialize(*args)
+ @env_table = {}
+ @stdinput = $stdin
+ super(*args)
+ end
+ attr_reader :env_table
+ end
+ $stdin = StringIO.new("")
+ cgi = CGIWrapper.new
+ cgi.env_table.update({
+ 'HTTPS' => 'off',
+ 'REQUEST_METHOD' => "GET",
+ 'HTTP_HOST' => #{[uri.host, uri.port].join(':').inspect},
+ 'SERVER_PORT' => #{uri.port.inspect},
+ 'REQUEST_URI' => #{uri.request_uri.inspect},
+ 'PATH_INFO' => #{uri.path.inspect},
+ 'QUERY_STRING' => #{uri.query.inspect}
+ })
+ require 'dispatcher' unless defined?(ActionController::Dispatcher)
+ Dispatcher.dispatch(cgi)
+ SCRIPT
+ File.open(File.join(RAILS_ROOT, 'request.rb'), 'w') { |file| file.write(request_script) }
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run("./script/runner -e production request.rb")
+ end
+end
+
+Then /^I should receive the following Hoptoad notification:$/ do |table|
+ exceptions = @terminal.output.scan(%r{Recieved the following exception:\n([^\n]*)\n}m)
+ exceptions.should_not be_empty
+
+ xml = exceptions.last[0]
+ doc = Nokogiri::XML.parse(xml)
+
+ hash = table.transpose.hashes.first
+
+ doc.should have_content('//error/message', hash['error message'])
+ doc.should have_content('//error/class', hash['error class'])
+ doc.should have_content('//request/url', hash['url'])
+
+ doc.should have_content('//component', hash['component']) if hash['component']
+ doc.should have_content('//action', hash['action']) if hash['action']
+
+ if hash['session']
+ session_key, session_value = hash['session'].split(': ')
+ doc.should have_content('//request/session/var/@key', session_key)
+ doc.should have_content('//request/session/var', session_value)
+ end
+
+ if hash['parameters']
+ param_key, param_value = hash['parameters'].split(': ')
+ doc.should have_content('//request/params/var/@key', param_key)
+ doc.should have_content('//request/params/var', param_value)
+ end
+end
+
+Then /^I should see the Rails version$/ do
+ Then %{I should see "[Rails: #{rails_version}]"}
+end
+
+Then /^I should see that "([^\"]*)" is not considered a framework gem$/ do |gem_name|
+ Then %{I should not see "[R] #{gem_name}"}
+end
+
+Then /^the command should have run successfully$/ do
+ @terminal.status.exitstatus.should == 0
+end
+
+When /^I route "([^\"]*)" to "([^\"]*)"$/ do |path, controller_action_pair|
+ route = if rails3?
+ %(match "#{path}", :to => "#{controller_action_pair}")
+ else
+ controller, action = controller_action_pair.split('#')
+ %(map.connect "#{path}", :controller => "#{controller}", :action => "#{action}")
+ end
+ routes_file = File.join(RAILS_ROOT, "config", "routes.rb")
+ File.open(routes_file, "r+") do |file|
+ content = file.read
+ content.gsub!(/^end$/, " #{route}\nend")
+ file.rewind
+ file.write(content)
+ end
+end
+
+Then /^"([^\"]*)" should not contain "([^\"]*)"$/ do |file_path, text|
+ actual_text = IO.read(File.join(RAILS_ROOT, file_path))
+ if actual_text.include?(text)
+ raise "Didn't expect text:\n#{actual_text}\nTo include:\n#{text}"
+ end
+end
+
+Then /^my Hoptoad configuration should contain the following line:$/ do |line|
+ configuration_file = if rails_supports_initializers?
+ rails_initializer_file
+ else
+ rails_non_initializer_hoptoad_config_file
+ # environment_path
+ end
+
+ configuration = File.read(configuration_file)
+ if ! configuration.include?(line.strip)
+ raise "Expected text:\n#{configuration}\nTo include:\n#{line}\nBut it didn't."
+ end
+end
+
+When /^I set the environment variable "([^\"]*)" to "([^\"]*)"$/ do |environment_variable, value|
+ @terminal.environment_variables[environment_variable] = value
+end
+
+When /^I configure the Heroku rake shim$/ do
+ @terminal.invoke_heroku_rake_tasks_locally = true
+end
+
+When /^I configure the application to filter parameter "([^\"]*)"$/ do |parameter|
+ if rails3?
+ application_filename = File.join(RAILS_ROOT, 'config', 'application.rb')
+ application_lines = File.open(application_filename).readlines
+
+ application_definition_line = application_lines.detect { |line| line =~ /Application/ }
+ application_definition_line_index = application_lines.index(application_definition_line)
+
+ application_lines.insert(application_definition_line_index + 1,
+ " config.filter_parameters += [#{parameter.inspect}]")
+
+ File.open(application_filename, "w") do |file|
+ file.puts application_lines.join("\n")
+ end
+ else
+ controller_filename = application_controller_filename
+ controller_lines = File.open(controller_filename).readlines
+
+ controller_definition_line = controller_lines.detect { |line| line =~ /ApplicationController/ }
+ controller_definition_line_index = controller_lines.index(controller_definition_line)
+
+ controller_lines.insert(controller_definition_line_index + 1,
+ " filter_parameter_logging #{parameter.inspect}")
+
+ File.open(controller_filename, "w") do |file|
+ file.puts controller_lines.join("\n")
+ end
+ end
+end
View
18 vendor/plugins/hoptoad_notifier/features/support/env.rb
@@ -0,0 +1,18 @@
+require 'active_support'
+require 'nokogiri'
+require 'spec'
+
+PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
+TEMP_DIR = File.join(PROJECT_ROOT, 'tmp').freeze
+RAILS_ROOT = File.join(TEMP_DIR, 'rails_root').freeze
+BUILT_GEM_ROOT = File.join(TEMP_DIR, 'built_gems').freeze
+LOCAL_GEM_ROOT = File.join(TEMP_DIR, 'local_gems').freeze
+RACK_FILE = File.join(TEMP_DIR, 'rack_app.rb').freeze
+
+Before do
+ FileUtils.mkdir_p(TEMP_DIR)
+ FileUtils.rm_rf(BUILT_GEM_ROOT)
+ FileUtils.rm_rf(RAILS_ROOT)
+ FileUtils.rm_f(RACK_FILE)
+ FileUtils.mkdir_p(BUILT_GEM_ROOT)
+end
View
7 vendor/plugins/hoptoad_notifier/features/support/hoptoad_shim.rb.template
@@ -0,0 +1,7 @@
+require 'sham_rack'
+
+ShamRack.at("hoptoadapp.com") do |env|
+ xml = env['rack.input'].read
+ puts "Recieved the following exception:\n#{xml}"
+ ["200 OK", { "Content-type" => "text/xml" }, "<notice/>"]
+end
View
24 vendor/plugins/hoptoad_notifier/features/support/matchers.rb
@@ -0,0 +1,24 @@
+module Matchers
+ def have_content(xpath, content)
+ simple_matcher "have #{content.inspect} at #{xpath}" do |doc, matcher|
+ elements = doc.search(xpath)
+ if elements.empty?
+ matcher.failure_message = "In XML:\n#{doc}\nNo element at #{xpath}"
+ false
+ else
+ element_with_content = doc.at("#{xpath}[contains(.,'#{content}')]")
+ if element_with_content.nil?
+ found = elements.collect { |element| element.content }
+ matcher.failure_message =
+ "In XML:\n#{doc}\n" +
+ "Got content #{found.inspect} at #{xpath} instead of #{content.inspect}"
+ false
+ else
+ true
+ end
+ end
+ end
+ end
+end
+
+World(Matchers)
View
77 vendor/plugins/hoptoad_notifier/features/support/rails.rb
@@ -0,0 +1,77 @@
+module RailsHelpers
+ def rails_root_exists?
+ File.exists?(environment_path)
+ end
+
+ def application_controller_filename
+ rails_version_is_2_2_or_less = rails_version =~ /^1\./ || rails_version =~ /^2.[012]/
+
+ if rails_version_is_2_2_or_less
+ controller_filename = File.join(RAILS_ROOT, 'app', 'controllers', "application.rb")
+ else
+ controller_filename = File.join(RAILS_ROOT, 'app', 'controllers', "application_controller.rb")
+ end
+ end
+
+ def rails3?
+ rails_version =~ /^3/
+ end
+
+ def rails_uses_rack?
+ rails3?
+ end
+
+ def rails_version
+ @rails_version ||= begin
+ if bundler_manages_gems?
+ rails_version = open(gemfile_path).read.match(/gem.*rails["'].*["'](.+)["']/)[1]
+ else
+ environment_file = File.join(RAILS_ROOT, 'config', 'environment.rb')
+ rails_version = `grep RAILS_GEM_VERSION #{environment_file}`.match(/[\d.]+/)[0]
+ end
+ end
+ end
+
+ def bundler_manages_gems?
+ File.exists?(gemfile_path)
+ end
+
+ def gemfile_path
+ gemfile = File.join(RAILS_ROOT, 'Gemfile')
+ end
+
+ def rails_manages_gems?
+ rails_version =~ /^2\.[123]/
+ end
+
+ def rails_supports_initializers?
+ rails3? || rails_version =~ /^2\./
+ end
+
+ def rails_finds_generators_in_gems?
+ rails3? || rails_version =~ /^2\./
+ end
+
+ def environment_path
+ File.join(RAILS_ROOT, 'config', 'environment.rb')
+ end
+
+ def bundle_gem(gem_name)
+ File.open(gemfile_path, 'a') do |file|
+ file.puts("gem '#{gem_name}'")
+ end
+ end
+
+ def config_gem(gem_name)
+ run = "Rails::Initializer.run do |config|"
+ insert = " config.gem '#{gem_name}'"
+ content = File.read(environment_path)
+ if content.sub!(run, "#{run}\n#{insert}")
+ File.open(environment_path, 'wb') { |file| file.write(content) }
+ else
+ raise "Couldn't find #{run.inspect} in #{environment_path}"
+ end
+ end
+end
+
+World(RailsHelpers)
View
92 vendor/plugins/hoptoad_notifier/features/support/terminal.rb
@@ -0,0 +1,92 @@
+require 'fileutils'
+
+Before do
+ @terminal = Terminal.new
+end
+
+class Terminal
+ attr_reader :output, :status
+ attr_accessor :environment_variables, :invoke_heroku_rake_tasks_locally
+
+ def initialize
+ @cwd = FileUtils.pwd
+ @output = ""
+ @status = 0
+ @logger = Logger.new(File.join(TEMP_DIR, 'terminal.log'))
+
+ @invoke_heroku_rake_tasks_locally = false
+
+ @environment_variables = {
+ "GEM_HOME" => LOCAL_GEM_ROOT,
+ "GEM_PATH" => "#{LOCAL_GEM_ROOT}:#{BUILT_GEM_ROOT}",
+ "PATH" => "#{gem_bin_path}:#{ENV['PATH']}"
+ }
+ end
+
+ def cd(directory)
+ @cwd = directory
+ end
+
+ def run(command)
+ command = optionally_invoke_heroku_rake_tasks_locally(command)
+
+ output << "#{command}\n"
+ FileUtils.cd(@cwd) do
+ cmdline = "#{environment_settings} #{command} 2>&1"
+ logger.debug(cmdline)
+ result = `#{cmdline}`
+ logger.debug(result)
+ output << result
+ end
+ @status = $?
+ end
+
+ def optionally_invoke_heroku_rake_tasks_locally(command)
+ if invoke_heroku_rake_tasks_locally
+ command.sub(/^heroku /, '')
+ else
+ command
+ end
+ end
+
+ def echo(string)
+ logger.debug(string)
+ end
+
+ def build_and_install_gem(gemspec)
+ pkg_dir = File.join(TEMP_DIR, 'pkg')
+ FileUtils.mkdir_p(pkg_dir)
+ output = `gem build #{gemspec} 2>&1`
+ gem_file = Dir.glob("*.gem").first
+ unless gem_file
+ raise "Gem didn't build:\n#{output}"
+ end
+ target = File.join(pkg_dir, gem_file)
+ FileUtils.mv(gem_file, target)
+ install_gem_to(BUILT_GEM_ROOT, target)
+ end
+
+ def install_gem(gem)
+ install_gem_to(LOCAL_GEM_ROOT, gem)
+ end
+
+ def uninstall_gem(gem)
+ `gem uninstall -i #{BUILT_GEM_ROOT} #{gem}`
+ end
+
+ private
+
+ def install_gem_to(root, gem)
+ `gem install -i #{root} --no-ri --no-rdoc #{gem}`
+ end
+
+ def environment_settings
+ @environment_variables.map { |key, value| "#{key}=#{value}" }.join(' ')
+ end
+
+ def gem_bin_path
+ File.join(LOCAL_GEM_ROOT, "bin")
+ end
+
+ attr_reader :logger
+end
View
63 vendor/plugins/hoptoad_notifier/generators/hoptoad/hoptoad_generator.rb
@@ -0,0 +1,63 @@
+require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
+require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
+
+class HoptoadGenerator < Rails::Generator::Base
+ def add_options!(opt)
+ opt.on('-k', '--api-key=key', String, "Your Hoptoad API key") {|v| options[:api_key] = v}
+ opt.on('-h', '--heroku', "Use the Heroku addon to provide your Hoptoad API key") {|v| options[:heroku] = v}
+ end
+
+ def manifest
+ if !api_key_configured? && !options[:api_key] && !options[:heroku]
+ puts "Must pass --api-key or --heroku or create config/initializers/hoptoad.rb"
+ exit
+ end
+ if plugin_is_present?
+ puts "You must first remove the hoptoad_notifier plugin. Please run: script/plugin remove hoptoad_notifier"
+ exit
+ end
+ record do |m|
+ m.directory 'lib/tasks'
+ m.file 'hoptoad_notifier_tasks.rake', 'lib/tasks/hoptoad_notifier_tasks.rake'
+ if ['config/deploy.rb', 'Capfile'].all? { |file| File.exists?(file) }
+ m.append_to 'config/deploy.rb', capistrano_hook
+ end
+ if api_key_expression
+ if use_initializer?
+ m.template 'initializer.rb', 'config/initializers/hoptoad.rb',
+ :assigns => {:api_key => api_key_expression}
+ else
+ m.template 'initializer.rb', 'config/hoptoad.rb',
+ :assigns => {:api_key => api_key_expression}
+ m.append_to 'config/environment.rb', "require 'config/hoptoad'"
+ end
+ end
+ m.rake "hoptoad:test", :generate_only => true
+ end
+ end
+
+ def api_key_expression
+ s = if options[:api_key]
+ "'#{options[:api_key]}'"
+ elsif options[:heroku]
+ "ENV['HOPTOAD_API_KEY']"
+ end
+ end
+
+ def use_initializer?
+ Rails::VERSION::MAJOR > 1
+ end
+
+ def api_key_configured?
+ File.exists?('config/initializers/hoptoad.rb') ||
+ system("grep HoptoadNotifier config/environment.rb")
+ end
+
+ def capistrano_hook
+ IO.read(source_path('capistrano_hook.rb'))
+ end
+
+ def plugin_is_present?
+ File.exists?('vendor/plugins/hoptoad_notifier')
+ end
+end
View
34 vendor/plugins/hoptoad_notifier/generators/hoptoad/lib/insert_commands.rb
@@ -0,0 +1,34 @@
+# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
+
+Rails::Generator::Commands::Base.class_eval do
+ def file_contains?(relative_destination, line)
+ File.read(destination_path(relative_destination)).include?(line)
+ end
+end
+
+Rails::Generator::Commands::Create.class_eval do
+ def append_to(file, line)
+ logger.insert "#{line} appended to #{file}"
+ unless options[:pretend] || file_contains?(file, line)
+ File.open(file, "a") do |file|
+ file.puts
+ file.puts line
+ end
+ end
+ end
+end
+
+Rails::Generator::Commands::Destroy.class_eval do
+ def append_to(file, line)
+ logger.remove "#{line} removed from #{file}"
+ unless options[:pretend]
+ gsub_file file, "\n#{line}", ''
+ end
+ end
+end
+
+Rails::Generator::Commands::List.class_eval do
+ def append_to(file, line)
+ logger.insert "#{line} appended to #{file}"
+ end
+end
View
24 vendor/plugins/hoptoad_notifier/generators/hoptoad/lib/rake_commands.rb
@@ -0,0 +1,24 @@
+Rails::Generator::Commands::Create.class_eval do
+ def rake(cmd, opts = {})
+ logger.rake "rake #{cmd}"
+ unless system("rake #{cmd}")
+ logger.rake "#{cmd} failed. Rolling back"
+ command(:destroy).invoke!
+ end
+ end
+end
+
+Rails::Generator::Commands::Destroy.class_eval do
+ def rake(cmd, opts = {})
+ unless opts[:generate_only]
+ logger.rake "rake #{cmd}"
+ system "rake #{cmd}"
+ end
+ end
+end
+
+Rails::Generator::Commands::List.class_eval do
+ def rake(cmd, opts = {})
+ logger.rake "rake #{cmd}"
+ end
+end
View
6 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/capistrano_hook.rb
@@ -0,0 +1,6 @@
+
+Dir[File.join(File.dirname(__FILE__), '..', 'vendor', 'gems', 'hoptoad_notifier-*')].each do |vendored_notifier|
+ $: << File.join(vendored_notifier, 'lib')
+end
+
+require 'hoptoad_notifier/capistrano'
View
25 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/hoptoad_notifier_tasks.rake
@@ -0,0 +1,25 @@
+# Don't load anything when running the gems:* tasks.
+# Otherwise, hoptoad_notifier will be considered a framework gem.
+# https://thoughtbot.lighthouseapp.com/projects/14221/tickets/629
+unless ARGV.any? {|a| a =~ /^gems/}
+
+ Dir[File.join(RAILS_ROOT, 'vendor', 'gems', 'hoptoad_notifier-*')].each do |vendored_notifier|
+ $: << File.join(vendored_notifier, 'lib')
+ end
+
+ begin
+ require 'hoptoad_notifier/tasks'
+ rescue LoadError => exception
+ namespace :hoptoad do
+ %w(deploy test log_stdout).each do |task_name|
+ desc "Missing dependency for hoptoad:#{task_name}"
+ task task_name do
+ $stderr.puts "Failed to run hoptoad:#{task_name} because of missing dependency."
+ $stderr.puts "You probably need to run `rake gems:install` to install the hoptoad_notifier gem"
+ abort exception.inspect
+ end
+ end
+ end
+ end
+
+end
View
6 vendor/plugins/hoptoad_notifier/generators/hoptoad/templates/initializer.rb
@@ -0,0 +1,6 @@
+<% if Rails::VERSION::MAJOR < 3 && Rails::VERSION::MINOR < 2 -%>
+require 'hoptoad_notifier/rails'
+<% end -%>
+HoptoadNotifier.configure do |config|
+ config.api_key = <%= api_key_expression %>
+end
View
32 vendor/plugins/hoptoad_notifier/ginger_scenarios.rb
@@ -0,0 +1,32 @@
+require 'ginger'
+
+def create_scenario(version)
+ scenario = Ginger::Scenario.new
+ scenario[/^active_?support$/] = version
+ scenario[/^active_?record$/] = version
+ scenario[/^action_?pack$/] = version
+ scenario[/^action_?controller$/] = version
+ scenario
+end
+
+Ginger.configure do |config|
+ config.aliases["active_record"] = "activerecord"
+ config.aliases["active_support"] = "activesupport"
+ config.aliases["action_controller"] = "actionpack"
+
+ rails_1_2_6 = Ginger::Scenario.new
+ rails_1_2_6[/^active_?support$/] = "1.4.4"
+ rails_1_2_6[/^active_?record$/] = "1.15.6"
+ rails_1_2_6[/^action_?pack$/] = "1.13.6"
+ rails_1_2_6[/^action_?controller$/] = "1.13.6"
+
+ config.scenarios << rails_1_2_6
+ config.scenarios << create_scenario("2.0.2")
+ config.scenarios << create_scenario("2.1.2")
+ config.scenarios << create_scenario("2.2.2")
+ config.scenarios << create_scenario("2.3.2")
+ # Rails 2.3.3 has broken params filtering
+ # config.scenarios << create_scenario("2.3.3")
+ config.scenarios << create_scenario("2.3.4")
+ config.scenarios << create_scenario("2.3.5")
+end
View
1  vendor/plugins/hoptoad_notifier/install.rb
@@ -0,0 +1 @@
+puts IO.read(File.join(File.dirname(__FILE__), 'INSTALL'))
View
148 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier.rb
@@ -0,0 +1,148 @@
+require 'net/http'
+require 'net/https'
+require 'rubygems'
+require 'active_support'
+require 'hoptoad_notifier/version'
+require 'hoptoad_notifier/configuration'
+require 'hoptoad_notifier/notice'
+require 'hoptoad_notifier/sender'
+require 'hoptoad_notifier/backtrace'
+require 'hoptoad_notifier/rack'
+
+require 'hoptoad_notifier/railtie' if defined?(Rails::Railtie)
+
+# Gem for applications to automatically post errors to the Hoptoad of their choice.
+module HoptoadNotifier
+
+ API_VERSION = "2.0"
+ LOG_PREFIX = "** [Hoptoad] "
+
+ HEADERS = {
+ 'Content-type' => 'text/xml',
+ 'Accept' => 'text/xml, application/xml'
+ }
+
+ class << self
+ # The sender object is responsible for delivering formatted data to the Hoptoad server.
+ # Must respond to #send_to_hoptoad. See HoptoadNotifier::Sender.
+ attr_accessor :sender
+
+ # A Hoptoad configuration object. Must act like a hash and return sensible
+ # values for all Hoptoad configuration options. See HoptoadNotifier::Configuration.
+ attr_accessor :configuration
+
+ # Tell the log that the Notifier is good to go
+ def report_ready
+ write_verbose_log("Notifier #{VERSION} ready to catch errors")
+ end
+
+ # Prints out the environment info to the log for debugging help
+ def report_environment_info
+ write_verbose_log("Environment Info: #{environment_info}")
+ end
+
+ # Prints out the response body from Hoptoad for debugging help
+ def report_response_body(response)
+ write_verbose_log("Response from Hoptoad: \n#{response}")
+ end
+
+ # Returns the Ruby version, Rails version, and current Rails environment
+ def environment_info
+ info = "[Ruby: #{RUBY_VERSION}]"
+ info << " [#{configuration.framework}]"
+ info << " [Env: #{configuration.environment_name}]"
+ end
+
+ # Writes out the given message to the #logger
+ def write_verbose_log(message)
+ logger.info LOG_PREFIX + message if logger
+ end
+
+ # Look for the Rails logger currently defined
+ def logger
+ self.configuration.logger
+ end
+
+ # Call this method to modify defaults in your initializers.
+ #
+ # @example
+ # HoptoadNotifier.configure do |config|
+ # config.api_key = '1234567890abcdef'
+ # config.secure = false
+ # end
+ def configure(silent = false)
+ self.configuration ||= Configuration.new
+ yield(configuration)
+ self.sender = Sender.new(configuration)
+ report_ready unless silent
+ end
+
+ # Sends an exception manually using this method, even when you are not in a controller.
+ #
+ # @param [Exception] exception The exception you want to notify Hoptoad about.
+ # @param [Hash] opts Data that will be sent to Hoptoad.
+ #
+ # @option opts [String] :api_key The API key for this project. The API key is a unique identifier that Hoptoad uses for identification.
+ # @option opts [String] :error_message The error returned by the exception (or the message you want to log).
+ # @option opts [String] :backtrace A backtrace, usually obtained with +caller+.
+ # @option opts [String] :request The controller's request object.
+ # @option opts [String] :session The contents of the user's session.
+ # @option opts [String] :environment ENV merged with the contents of the request's environment.
+ def notify(exception, opts = {})
+ send_notice(build_notice_for(exception, opts))
+ end
+
+ # Sends the notice unless it is one of the default ignored exceptions
+ # @see HoptoadNotifier.notify
+ def notify_or_ignore(exception, opts = {})
+ notice = build_notice_for(exception, opts)
+ send_notice(notice) unless notice.ignore?
+ end
+
+ def build_lookup_hash_for(exception, options = {})
+ notice = build_notice_for(exception, options)
+
+ result = {}
+ result[:action] = notice.action rescue nil
+ result[:component] = notice.component rescue nil
+ result[:error_class] = notice.error_class if notice.error_class
+ result[:environment_name] = 'production'
+
+ unless notice.backtrace.lines.empty?
+ result[:file] = notice.backtrace.lines.first.file
+ result[:line_number] = notice.backtrace.lines.first.number
+ end
+
+ result
+ end
+
+ private
+
+ def send_notice(notice)
+ if configuration.public?
+ sender.send_to_hoptoad(notice.to_xml)
+ end
+ end
+
+ def build_notice_for(exception, opts = {})
+ exception = unwrap_exception(exception)
+ if exception.respond_to?(:to_hash)
+ opts = opts.merge(exception)
+ else
+ opts = opts.merge(:exception => exception)
+ end
+ Notice.new(configuration.merge(opts))
+ end
+
+ def unwrap_exception(exception)
+ if exception.respond_to?(:original_exception)
+ exception.original_exception
+ elsif exception.respond_to?(:continued_exception)
+ exception.continued_exception
+ else
+ exception
+ end
+ end
+ end
+end
+
View
99 vendor/plugins/hoptoad_notifier/lib/hoptoad_notifier/backtrace.rb
@@ -0,0 +1,99 @@
+module HoptoadNotifier
+ # Front end to parsing the backtrace for each notice
+ class Backtrace
+
+ # Handles backtrace parsing line by line
+ class Line
+
+ INPUT_FORMAT = %r{^([^:]+):(\d+)(?::in `([^']+)')?$}.freeze
+
+ # The file portion of the line (such as app/models/user.rb)
+ attr_reader :file
+
+ # The line number portion of the line
+ attr_reader :number
+
+ # The method of the line (such as index)
+ attr_reader :method
+
+ # Parses a single line of a given backtrace
+ # @param [String] unparsed_line The raw line from +caller+ or some backtrace
+ # @return [Line] The parsed backtrace line
+ def self.parse(unparsed_line)
+ _, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
+ new(file, number, method)
+ end
+
+ def initialize(file, number, method)
+ self.file = file
+ self.number = number
+ self.method = method
+ end
+
+ # Reconstructs the line in a readable fashion
+ def to_s
+ "#{file}:#{number}:in `#{method}'"
+ end
+
+ def ==(other)
+ to_s == other.to_s
+ end
+
+ def inspect
+ "<Line:#{to_s}>"
+ end
+
+ private
+
+ attr_writer :file, :number, :method
+ end
+
+ # holder for an Array of Backtrace::Line instances
+ attr_reader :lines
+
+ def self.parse(ruby_backtrace, opts = {})
+ ruby_lines = split_multiline_backtrace(ruby_backtrace)
+
+ filters = opts[:filters] || []
+ filtered_lines = ruby_lines.to_a.map do |line|
+ filters.inject(line) do |line, proc|
+ proc.call(line)
+ end
+ end.compact
+
+ lines = filtered_lines.collect do |unparsed_line|
+ Line.parse(unparsed_line)
+ end
+
+ instance = new(lines)
+ end
+
+ def initialize(lines)
+ self.lines = lines
+ end
+
+ def inspect
+ "<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
+ end
+
+ def ==(other)
+ if other.respond_to?(:lines)
+ lines == other.lines