better_errors 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of better_errors might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe0694430a61558b1ad22a156922e9a162b02352
4
- data.tar.gz: 6804d151297037d1eb778143d3eb807fe7573e9d
3
+ metadata.gz: bc36d3113c7041816a7697fbd1e50333f5976003
4
+ data.tar.gz: 834f3f4a4903a45f150d83adde3f25452d2fd86b
5
5
  SHA512:
6
- metadata.gz: 3d0c58b00e4b6965e8dfd3ae3ded8a9efbfde40f8878854cf3ed86b46a5b344e647a73e24f541de858ea1f9f1b6b6c5b29145896b73870ac3eb34219edafb9db
7
- data.tar.gz: 5fc01d0bd170e712c28d0efde81fa177eff86b6b36862bef1217749e1b39778c6e97e1899bed429f66dfaecfee45de843328935fe746402508892657232cf7aa
6
+ metadata.gz: 130d61a4ce2e5509eb1585dfa0e3c620bf54387ac6a0931d1a534296460a0e06601a6d71ce41b3d3ffbd15951626ddfd7e753bb1bc911c35cf76cfa52cfcd771
7
+ data.tar.gz: 5906697a352187036b92cdefe124fea459405d7e3cc80f3bcc6f07c7a2952f328367f452e88272947edef464a4cc75fbe3d276c24580b9b633b6f9e60c99a60d
data/.gitignore CHANGED
@@ -1,6 +1,8 @@
1
1
  *.gem
2
- tmp
3
- Gemfile.lock
4
- coverage
5
- .yardoc
6
- doc
2
+ /tmp
3
+ /Gemfile.lock
4
+ /coverage
5
+ /.yardoc
6
+ /doc
7
+ /.bundle
8
+ /vendor/gems
@@ -1,6 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.0
3
4
  - 2.0.0
4
- - 1.9.3
5
- - 1.9.2
6
- - jruby-1.7.4
data/Gemfile CHANGED
@@ -3,9 +3,9 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem "rake"
6
+ gem "rack"
6
7
  gem "rspec", "2.14.1"
7
8
  gem "binding_of_caller", platforms: :ruby
8
9
  gem "pry", "0.9.12"
9
- gem "simplecov"
10
10
  gem "yard"
11
11
  gem "kramdown"
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Charlie Somerville
1
+ Copyright (c) 2014 Charlie Somerville
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Better Errors [![Build Status](https://travis-ci.org/charliesome/better_errors.png)](https://travis-ci.org/charliesome/better_errors) [![Code Climate](https://codeclimate.com/github/charliesome/better_errors.png)](https://codeclimate.com/github/charliesome/better_errors)
1
+ # Better Errors [![Gem Version](http://img.shields.io/gem/v/better_errors.svg)](https://rubygems.org/gems/better_errors) [![Build Status](https://travis-ci.org/charliesome/better_errors.svg)](https://travis-ci.org/charliesome/better_errors) [![Code Climate](http://img.shields.io/codeclimate/github/charliesome/better_errors.svg)](https://codeclimate.com/github/charliesome/better_errors)
2
2
 
3
3
  Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails in any Rack app as Rack middleware.
4
4
 
@@ -29,6 +29,8 @@ gem "binding_of_caller"
29
29
 
30
30
  This is an optional dependency however, and Better Errors will work without it.
31
31
 
32
+ _Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._
33
+
32
34
  ## Security
33
35
 
34
36
  **NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.**
data/Rakefile CHANGED
@@ -1,4 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
- task :default => :spec
3
- task :test => :spec
4
- task :spec do sh 'bundle exec rspec' end
2
+ require "rspec/core/rake_task"
3
+
4
+ namespace :test do
5
+ RSpec::Core::RakeTask.new(:with_binding_of_caller)
6
+
7
+ without_task = RSpec::Core::RakeTask.new(:without_binding_of_caller)
8
+ without_task.ruby_opts = "-I spec -r without_binding_of_caller"
9
+
10
+ task :all => [:with_binding_of_caller, :without_binding_of_caller]
11
+ end
12
+
13
+ task :default => "test:all"
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'better_errors/version'
@@ -17,10 +16,11 @@ Gem::Specification.new do |s|
17
16
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
17
  s.require_paths = ["lib"]
19
18
 
20
- s.required_ruby_version = ">= 1.9.2"
21
-
19
+ s.required_ruby_version = ">= 2.0.0"
20
+
22
21
  s.add_dependency "erubis", ">= 2.6.6"
23
22
  s.add_dependency "coderay", ">= 1.0.0"
23
+ s.add_dependency "rack", ">= 0.9.0"
24
24
 
25
25
  # optional dependencies:
26
26
  # s.add_dependency "binding_of_caller"
@@ -3,12 +3,13 @@ require "erubis"
3
3
  require "coderay"
4
4
  require "uri"
5
5
 
6
- require "better_errors/version"
6
+ require "better_errors/code_formatter"
7
7
  require "better_errors/error_page"
8
- require "better_errors/stack_frame"
9
8
  require "better_errors/middleware"
10
- require "better_errors/code_formatter"
9
+ require "better_errors/raised_exception"
11
10
  require "better_errors/repl"
11
+ require "better_errors/stack_frame"
12
+ require "better_errors/version"
12
13
 
13
14
  module BetterErrors
14
15
  POSSIBLE_EDITOR_PRESETS = [
@@ -136,11 +137,10 @@ end
136
137
 
137
138
  begin
138
139
  require "binding_of_caller"
140
+ require "better_errors/exception_extension"
139
141
  BetterErrors.binding_of_caller_available = true
140
142
  rescue LoadError => e
141
143
  BetterErrors.binding_of_caller_available = false
142
144
  end
143
145
 
144
- require "better_errors/core_ext/exception"
145
-
146
146
  require "better_errors/rails" if defined? Rails::Railtie
@@ -1,5 +1,6 @@
1
1
  require "cgi"
2
2
  require "json"
3
+ require "securerandom"
3
4
 
4
5
  module BetterErrors
5
6
  # @private
@@ -7,42 +8,46 @@ module BetterErrors
7
8
  def self.template_path(template_name)
8
9
  File.expand_path("../templates/#{template_name}.erb", __FILE__)
9
10
  end
10
-
11
+
11
12
  def self.template(template_name)
12
13
  Erubis::EscapedEruby.new(File.read(template_path(template_name)))
13
14
  end
14
-
15
+
15
16
  attr_reader :exception, :env, :repls
16
-
17
+
17
18
  def initialize(exception, env)
18
- @exception = real_exception(exception)
19
+ @exception = RaisedException.new(exception)
19
20
  @env = env
20
21
  @start_time = Time.now.to_f
21
22
  @repls = []
22
23
  end
23
-
24
+
25
+ def id
26
+ @id ||= SecureRandom.hex(8)
27
+ end
28
+
24
29
  def render(template_name = "main")
25
30
  self.class.template(template_name).result binding
26
31
  end
27
-
32
+
28
33
  def do_variables(opts)
29
34
  index = opts["index"].to_i
30
35
  @frame = backtrace_frames[index]
31
36
  @var_start_time = Time.now.to_f
32
37
  { html: render("variable_info") }
33
38
  end
34
-
39
+
35
40
  def do_eval(opts)
36
41
  index = opts["index"].to_i
37
42
  code = opts["source"]
38
-
43
+
39
44
  unless binding = backtrace_frames[index].frame_binding
40
45
  return { error: "REPL unavailable in this stack frame" }
41
46
  end
42
-
47
+
43
48
  result, prompt, prefilled_input =
44
49
  (@repls[index] ||= REPL.provider.new(binding)).send_input(code)
45
-
50
+
46
51
  { result: result,
47
52
  prompt: prompt,
48
53
  prefilled_input: prefilled_input,
@@ -50,22 +55,22 @@ module BetterErrors
50
55
  end
51
56
 
52
57
  def backtrace_frames
53
- @backtrace_frames ||= StackFrame.from_exception(exception)
58
+ exception.backtrace
54
59
  end
55
60
 
56
61
  def application_frames
57
- backtrace_frames.select { |frame| frame.context == :application }
62
+ backtrace_frames.select(&:application?)
58
63
  end
59
64
 
60
65
  def first_frame
61
- backtrace_frames.detect { |frame| frame.context == :application } || backtrace_frames.first
66
+ application_frames.first || backtrace_frames.first
62
67
  end
63
-
68
+
64
69
  private
65
70
  def editor_url(frame)
66
71
  BetterErrors.editor[frame.filename, frame.line]
67
72
  end
68
-
73
+
69
74
  def rack_session
70
75
  env['rack.session']
71
76
  end
@@ -77,31 +82,15 @@ module BetterErrors
77
82
  def uri_prefix
78
83
  env["SCRIPT_NAME"] || ""
79
84
  end
80
-
81
- def exception_message
82
- if exception.is_a?(SyntaxError) && exception.message =~ /\A.*:\d*: (.*)$/
83
- $1
84
- else
85
- exception.message
86
- end
87
- end
88
85
 
89
- def real_exception(exception)
90
- if exception.respond_to?(:original_exception) && exception.original_exception.is_a?(Exception)
91
- exception.original_exception
92
- else
93
- exception
94
- end
95
- end
96
-
97
86
  def request_path
98
87
  env["PATH_INFO"]
99
88
  end
100
-
89
+
101
90
  def html_formatted_code_block(frame)
102
91
  CodeFormatter::HTML.new(frame.filename, frame.line).output
103
92
  end
104
-
93
+
105
94
  def text_formatted_code_block(frame)
106
95
  CodeFormatter::Text.new(frame.filename, frame.line).output
107
96
  end
@@ -0,0 +1,17 @@
1
+ module BetterErrors
2
+ module ExceptionExtension
3
+ prepend_features Exception
4
+
5
+ def set_backtrace(*)
6
+ if caller_locations.none? { |loc| loc.path == __FILE__ }
7
+ @__better_errors_bindings_stack = ::Kernel.binding.callers.drop(1)
8
+ end
9
+
10
+ super
11
+ end
12
+
13
+ def __better_errors_bindings_stack
14
+ @__better_errors_bindings_stack || []
15
+ end
16
+ end
17
+ end
@@ -1,6 +1,7 @@
1
1
  require "json"
2
2
  require "ipaddr"
3
3
  require "set"
4
+ require "rack"
4
5
 
5
6
  module BetterErrors
6
7
  # Better Errors' error handling middleware. Including this in your middleware
@@ -62,16 +63,15 @@ module BetterErrors
62
63
  private
63
64
 
64
65
  def allow_ip?(env)
65
- # REMOTE_ADDR is not in the rack spec, so some application servers do
66
- # not provide it.
67
- return true unless env["REMOTE_ADDR"] and !env["REMOTE_ADDR"].strip.empty?
68
- ip = IPAddr.new env["REMOTE_ADDR"].split("%").first
66
+ request = Rack::Request.new(env)
67
+ return true unless request.ip and !request.ip.strip.empty?
68
+ ip = IPAddr.new request.ip.split("%").first
69
69
  ALLOWED_IPS.any? { |subnet| subnet.include? ip }
70
70
  end
71
71
 
72
72
  def better_errors_call(env)
73
73
  case env["PATH_INFO"]
74
- when %r{/__better_errors/(?<oid>-?\d+)/(?<method>\w+)\z}
74
+ when %r{/__better_errors/(?<id>.+?)/(?<method>\w+)\z}
75
75
  internal_call env, $~
76
76
  when %r{/__better_errors/?\z}
77
77
  show_error_page env
@@ -115,7 +115,7 @@ module BetterErrors
115
115
  def log_exception
116
116
  return unless BetterErrors.logger
117
117
 
118
- message = "\n#{@error_page.exception.class} - #{@error_page.exception.message}:\n"
118
+ message = "\n#{@error_page.exception.type} - #{@error_page.exception.message}:\n"
119
119
  @error_page.backtrace_frames.each do |frame|
120
120
  message << " #{frame}\n"
121
121
  end
@@ -124,7 +124,7 @@ module BetterErrors
124
124
  end
125
125
 
126
126
  def internal_call(env, opts)
127
- if opts[:oid].to_i != @error_page.object_id
127
+ if opts[:id] != @error_page.id
128
128
  return [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(error: "Session expired")]]
129
129
  end
130
130
 
@@ -0,0 +1,66 @@
1
+ # @private
2
+ module BetterErrors
3
+ class RaisedException
4
+ attr_reader :exception, :message, :backtrace
5
+
6
+ def initialize(exception)
7
+ if exception.respond_to?(:original_exception) && exception.original_exception
8
+ exception = exception.original_exception
9
+ end
10
+
11
+ @exception = exception
12
+ @message = exception.message
13
+
14
+ setup_backtrace
15
+ massage_syntax_error
16
+ end
17
+
18
+ def type
19
+ exception.class
20
+ end
21
+
22
+ private
23
+ def has_bindings?
24
+ exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
25
+ end
26
+
27
+ def setup_backtrace
28
+ if has_bindings?
29
+ setup_backtrace_from_bindings
30
+ else
31
+ setup_backtrace_from_backtrace
32
+ end
33
+ end
34
+
35
+ def setup_backtrace_from_bindings
36
+ @backtrace = exception.__better_errors_bindings_stack.map { |binding|
37
+ file = binding.eval "__FILE__"
38
+ line = binding.eval "__LINE__"
39
+ name = binding.frame_description
40
+ StackFrame.new(file, line, name, binding)
41
+ }
42
+ end
43
+
44
+ def setup_backtrace_from_backtrace
45
+ @backtrace = (exception.backtrace || []).map { |frame|
46
+ if /\A(?<file>.*?):(?<line>\d+)(:in `(?<name>.*)')?/ =~ frame
47
+ StackFrame.new(file, line.to_i, name)
48
+ end
49
+ }.compact
50
+ end
51
+
52
+ def massage_syntax_error
53
+ case exception.class.to_s
54
+ when "Haml::SyntaxError"
55
+ if /\A(.+?):(\d+)/ =~ exception.backtrace.first
56
+ backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
57
+ end
58
+ when "SyntaxError"
59
+ if /\A(.+?):(\d+): (.*)/m =~ exception.message
60
+ backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
61
+ @message = $3
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -36,8 +36,8 @@ module BetterErrors
36
36
  @fiber = Fiber.new do
37
37
  @pry.repl binding
38
38
  end
39
- @input = Input.new
40
- @output = Output.new
39
+ @input = BetterErrors::REPL::Pry::Input.new
40
+ @output = BetterErrors::REPL::Pry::Output.new
41
41
  @pry = ::Pry.new input: @input, output: @output
42
42
  @pry.hooks.clear_all if defined?(@pry.hooks.clear_all)
43
43
  @fiber.resume
@@ -4,49 +4,7 @@ module BetterErrors
4
4
  # @private
5
5
  class StackFrame
6
6
  def self.from_exception(exception)
7
- if has_binding_stack?(exception)
8
- list = exception.__better_errors_bindings_stack.map { |binding|
9
- file = binding.eval "__FILE__"
10
- line = binding.eval "__LINE__"
11
- name = binding.frame_description
12
- StackFrame.new(file, line, name, binding)
13
- }
14
- else
15
- list = (exception.backtrace || []).map { |frame|
16
- next unless md = /\A(?<file>.*?):(?<line>\d+)(:in `(?<name>.*)')?/.match(frame)
17
- StackFrame.new(md[:file], md[:line].to_i, md[:name])
18
- }.compact
19
- end
20
-
21
- if syntax_error?(exception)
22
- if trace = exception.backtrace and trace.first =~ /\A(.*):(\d+)/
23
- list.unshift StackFrame.new($1, $2.to_i, "")
24
- end
25
- end
26
-
27
- list
28
- end
29
-
30
- def self.syntax_error_classes
31
- # Better Errors may be loaded before some of the gems that provide these
32
- # classes, so we lazily set up the set of syntax error classes at runtime
33
- # after everything has hopefully had a chance to load.
34
- #
35
- @syntax_error_classes ||= begin
36
- class_names = %w[
37
- Haml::SyntaxError
38
- ]
39
-
40
- Set.new(class_names.map { |klass| eval(klass) rescue nil }.compact)
41
- end
42
- end
43
-
44
- def self.syntax_error?(exception)
45
- exception.is_a?(SyntaxError) || syntax_error_classes.include?(exception.class)
46
- end
47
-
48
- def self.has_binding_stack?(exception)
49
- exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
7
+ RaisedException.new(exception).backtrace
50
8
  end
51
9
 
52
10
  attr_reader :filename, :line, :name, :frame_binding
@@ -111,15 +69,10 @@ module BetterErrors
111
69
  def local_variables
112
70
  return {} unless frame_binding
113
71
  frame_binding.eval("local_variables").each_with_object({}) do |name, hash|
114
- begin
115
- if defined?(frame_binding.local_variable_get)
116
- hash[name] = frame_binding.local_variable_get(name)
117
- else
118
- hash[name] = frame_binding.eval(name.to_s)
119
- end
120
- rescue NameError => e
121
- # local_variables sometimes returns broken variables.
122
- # https://bugs.ruby-lang.org/issues/7536
72
+ if defined?(frame_binding.local_variable_get)
73
+ hash[name] = frame_binding.local_variable_get(name)
74
+ else
75
+ hash[name] = frame_binding.eval(name.to_s)
123
76
  end
124
77
  end
125
78
  end
@@ -141,14 +94,12 @@ module BetterErrors
141
94
 
142
95
  private
143
96
  def set_pretty_method_name
144
- return if RUBY_VERSION < "2.0.0"
145
-
146
97
  name =~ /\A(block (\([^)]+\) )?in )?/
147
98
  recv = frame_binding.eval("self")
148
99
 
149
100
  return unless method_name = frame_binding.eval("::Kernel.__method__")
150
101
 
151
- if Kernel.instance_method(:is_a?).bind(recv).call Module
102
+ if Module === recv
152
103
  @class_name = "#{$1}#{recv}"
153
104
  @method_name = ".#{method_name}"
154
105
  else
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title><%= exception.class %> at <%= request_path %></title>
4
+ <title><%= exception.type %> at <%= request_path %></title>
5
5
  </head>
6
6
  <body>
7
7
  <%# Stylesheets are placed in the <body> for Turbolinks compatibility. %>
@@ -731,8 +731,8 @@
731
731
 
732
732
  <div class='top'>
733
733
  <header class="exception">
734
- <h2><strong><%= exception.class %></strong> <span>at <%= request_path %></span></h2>
735
- <p><%= exception_message %></p>
734
+ <h2><strong><%= exception.type %></strong> <span>at <%= request_path %></span></h2>
735
+ <p><%= exception.message %></p>
736
736
  </header>
737
737
  </div>
738
738
 
@@ -768,7 +768,7 @@
768
768
  <script>
769
769
  (function() {
770
770
 
771
- var OID = <%== object_id.to_s.inspect %>;
771
+ var OID = "<%= id %>";
772
772
 
773
773
  var previousFrame = null;
774
774
  var previousFrameInfo = null;
@@ -1,6 +1,6 @@
1
- <%== text_heading("=", "%s at %s" % [exception.class, request_path]) %>
1
+ <%== text_heading("=", "%s at %s" % [exception.type, request_path]) %>
2
2
 
3
- > <%== exception_message %>
3
+ > <%== exception.message %>
4
4
  <% if backtrace_frames.any? %>
5
5
 
6
6
  <%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %>
@@ -1,3 +1,3 @@
1
1
  module BetterErrors
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -40,6 +40,14 @@ module BetterErrors
40
40
  app.call("REMOTE_ADDR" => "77.55.33.11")
41
41
  end
42
42
 
43
+ it "respects the X-Forwarded-For header" do
44
+ app.should_not_receive :better_errors_call
45
+ app.call(
46
+ "REMOTE_ADDR" => "127.0.0.1",
47
+ "HTTP_X_FORWARDED_FOR" => "1.2.3.4",
48
+ )
49
+ end
50
+
43
51
  it "doesn't blow up when given a blank REMOTE_ADDR" do
44
52
  expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error
45
53
  end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ module BetterErrors
4
+ describe RaisedException do
5
+ let(:exception) { RuntimeError.new("whoops") }
6
+ subject { RaisedException.new(exception) }
7
+
8
+ its(:exception) { should == exception }
9
+ its(:message) { should == "whoops" }
10
+ its(:type) { should == RuntimeError }
11
+
12
+ context "when the exception wraps another exception" do
13
+ let(:original_exception) { RuntimeError.new("something went wrong!") }
14
+ let(:exception) { double(:original_exception => original_exception) }
15
+
16
+ its(:exception) { should == original_exception }
17
+ its(:message) { should == "something went wrong!" }
18
+ end
19
+
20
+ context "when the exception is a syntax error" do
21
+ let(:exception) { SyntaxError.new("foo.rb:123: you made a typo!") }
22
+
23
+ its(:message) { should == "you made a typo!" }
24
+ its(:type) { should == SyntaxError }
25
+
26
+ it "has the right filename and line number in the backtrace" do
27
+ subject.backtrace.first.filename.should == "foo.rb"
28
+ subject.backtrace.first.line.should == 123
29
+ end
30
+ end
31
+
32
+ context "when the exception is a HAML syntax error" do
33
+ before do
34
+ stub_const("Haml::SyntaxError", Class.new(SyntaxError))
35
+ end
36
+
37
+ let(:exception) {
38
+ Haml::SyntaxError.new("you made a typo!").tap do |ex|
39
+ ex.set_backtrace(["foo.rb:123", "haml/internals/blah.rb:123456"])
40
+ end
41
+ }
42
+
43
+ its(:message) { should == "you made a typo!" }
44
+ its(:type) { should == Haml::SyntaxError }
45
+
46
+ it "has the right filename and line number in the backtrace" do
47
+ subject.backtrace.first.filename.should == "foo.rb"
48
+ subject.backtrace.first.line.should == 123
49
+ end
50
+ end
51
+ end
52
+ end
@@ -6,77 +6,77 @@ module BetterErrors
6
6
  it "is true for application filenames" do
7
7
  BetterErrors.stub(:application_root).and_return("/abc/xyz")
8
8
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
9
-
9
+
10
10
  frame.application?.should be_true
11
11
  end
12
-
12
+
13
13
  it "is false for everything else" do
14
14
  BetterErrors.stub(:application_root).and_return("/abc/xyz")
15
15
  frame = StackFrame.new("/abc/nope", 123, "foo")
16
-
16
+
17
17
  frame.application?.should be_false
18
18
  end
19
-
19
+
20
20
  it "doesn't care if no application_root is set" do
21
21
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
22
-
22
+
23
23
  frame.application?.should be_false
24
24
  end
25
25
  end
26
-
26
+
27
27
  context "#gem?" do
28
28
  it "is true for gem filenames" do
29
29
  Gem.stub(:path).and_return(["/abc/xyz"])
30
30
  frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
31
-
31
+
32
32
  frame.gem?.should be_true
33
33
  end
34
-
34
+
35
35
  it "is false for everything else" do
36
36
  Gem.stub(:path).and_return(["/abc/xyz"])
37
37
  frame = StackFrame.new("/abc/nope", 123, "foo")
38
-
38
+
39
39
  frame.gem?.should be_false
40
40
  end
41
41
  end
42
-
42
+
43
43
  context "#application_path" do
44
44
  it "chops off the application root" do
45
45
  BetterErrors.stub(:application_root).and_return("/abc/xyz")
46
46
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
47
-
47
+
48
48
  frame.application_path.should == "app/controllers/crap_controller.rb"
49
49
  end
50
50
  end
51
-
51
+
52
52
  context "#gem_path" do
53
53
  it "chops of the gem path and stick (gem) there" do
54
54
  Gem.stub(:path).and_return(["/abc/xyz"])
55
55
  frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
56
-
56
+
57
57
  frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
58
58
  end
59
-
59
+
60
60
  it "prioritizes gem path over application path" do
61
61
  BetterErrors.stub(:application_root).and_return("/abc/xyz")
62
62
  Gem.stub(:path).and_return(["/abc/xyz/vendor"])
63
63
  frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
64
-
64
+
65
65
  frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb"
66
66
  end
67
67
  end
68
-
68
+
69
69
  context "#pretty_path" do
70
70
  it "returns #application_path for application paths" do
71
71
  BetterErrors.stub(:application_root).and_return("/abc/xyz")
72
72
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index")
73
73
  frame.pretty_path.should == frame.application_path
74
74
  end
75
-
75
+
76
76
  it "returns #gem_path for gem paths" do
77
77
  Gem.stub(:path).and_return(["/abc/xyz"])
78
78
  frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo")
79
-
79
+
80
80
  frame.pretty_path.should == frame.gem_path
81
81
  end
82
82
  end
@@ -90,28 +90,28 @@ module BetterErrors
90
90
  frames.first.filename.should == "my_file.rb"
91
91
  frames.first.line.should == 123
92
92
  end
93
-
93
+
94
94
  it "doesn't blow up if no method name is given" do
95
95
  error = StandardError.allocate
96
-
96
+
97
97
  error.stub(:backtrace).and_return(["foo.rb:123"])
98
98
  frames = StackFrame.from_exception(error)
99
99
  frames.first.filename.should == "foo.rb"
100
100
  frames.first.line.should == 123
101
-
101
+
102
102
  error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"])
103
103
  frames = StackFrame.from_exception(error)
104
104
  frames.first.filename.should == "foo.rb"
105
105
  frames.first.line.should == 123
106
106
  end
107
-
107
+
108
108
  it "ignores a backtrace line if its format doesn't make any sense at all" do
109
109
  error = StandardError.allocate
110
110
  error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"])
111
111
  frames = StackFrame.from_exception(error)
112
112
  frames.count.should == 2
113
113
  end
114
-
114
+
115
115
  it "doesn't blow up if a filename contains a colon" do
116
116
  error = StandardError.allocate
117
117
  error.stub(:backtrace).and_return(["crap:filename.rb:123"])
@@ -125,11 +125,7 @@ module BetterErrors
125
125
  ::Kernel.binding
126
126
  end
127
127
  frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding)
128
- if RUBY_VERSION >= "2.0.0"
129
- frame.class_name.should == 'BasicObject'
130
- else
131
- frame.class_name.should be_nil
132
- end
128
+ frame.class_name.should == 'BasicObject'
133
129
  end
134
130
 
135
131
  it "sets method names properly" do
@@ -143,12 +139,12 @@ module BetterErrors
143
139
  end
144
140
 
145
141
  frame = StackFrame.from_exception(obj.my_method).first
146
- if RUBY_VERSION >= "2.0.0"
142
+ if BetterErrors.binding_of_caller_available?
147
143
  frame.method_name.should == "#my_method"
148
144
  frame.class_name.should == "String"
149
145
  else
150
146
  frame.method_name.should == "my_method"
151
- frame.class_name.should be_nil
147
+ frame.class_name.should == nil
152
148
  end
153
149
  end
154
150
 
@@ -1,7 +1,5 @@
1
- require "simplecov"
2
- SimpleCov.start
3
-
4
1
  $: << File.expand_path("../../lib", __FILE__)
2
+
5
3
  ENV["EDITOR"] = nil
4
+
6
5
  require "better_errors"
7
- require "ostruct"
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ alias_method :require_with_binding_of_caller, :require
3
+
4
+ def require(feature)
5
+ raise LoadError if feature == "binding_of_caller"
6
+
7
+ require_with_binding_of_caller(feature)
8
+ end
9
+ end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Somerville
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-23 00:00:00.000000000 Z
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.6.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.6.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: coderay
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.0
41
55
  description: Provides a better error page for Rails and other Rack apps. Includes
42
56
  source code inspection, a live REPL and local/instance variable inspection for all
43
57
  stack frames.
@@ -47,9 +61,9 @@ executables: []
47
61
  extensions: []
48
62
  extra_rdoc_files: []
49
63
  files:
50
- - .gitignore
51
- - .travis.yml
52
- - .yardopts
64
+ - ".gitignore"
65
+ - ".travis.yml"
66
+ - ".yardopts"
53
67
  - CHANGELOG.md
54
68
  - Gemfile
55
69
  - LICENSE.txt
@@ -60,10 +74,11 @@ files:
60
74
  - lib/better_errors/code_formatter.rb
61
75
  - lib/better_errors/code_formatter/html.rb
62
76
  - lib/better_errors/code_formatter/text.rb
63
- - lib/better_errors/core_ext/exception.rb
64
77
  - lib/better_errors/error_page.rb
78
+ - lib/better_errors/exception_extension.rb
65
79
  - lib/better_errors/middleware.rb
66
80
  - lib/better_errors/rails.rb
81
+ - lib/better_errors/raised_exception.rb
67
82
  - lib/better_errors/repl.rb
68
83
  - lib/better_errors/repl/basic.rb
69
84
  - lib/better_errors/repl/pry.rb
@@ -75,6 +90,7 @@ files:
75
90
  - spec/better_errors/code_formatter_spec.rb
76
91
  - spec/better_errors/error_page_spec.rb
77
92
  - spec/better_errors/middleware_spec.rb
93
+ - spec/better_errors/raised_exception_spec.rb
78
94
  - spec/better_errors/repl/basic_spec.rb
79
95
  - spec/better_errors/repl/pry_spec.rb
80
96
  - spec/better_errors/repl/shared_examples.rb
@@ -82,6 +98,7 @@ files:
82
98
  - spec/better_errors/support/my_source.rb
83
99
  - spec/better_errors_spec.rb
84
100
  - spec/spec_helper.rb
101
+ - spec/without_binding_of_caller.rb
85
102
  homepage: https://github.com/charliesome/better_errors
86
103
  licenses:
87
104
  - MIT
@@ -92,17 +109,17 @@ require_paths:
92
109
  - lib
93
110
  required_ruby_version: !ruby/object:Gem::Requirement
94
111
  requirements:
95
- - - '>='
112
+ - - ">="
96
113
  - !ruby/object:Gem::Version
97
- version: 1.9.2
114
+ version: 2.0.0
98
115
  required_rubygems_version: !ruby/object:Gem::Requirement
99
116
  requirements:
100
- - - '>='
117
+ - - ">="
101
118
  - !ruby/object:Gem::Version
102
119
  version: '0'
103
120
  requirements: []
104
121
  rubyforge_project:
105
- rubygems_version: 2.0.3
122
+ rubygems_version: 2.2.2
106
123
  signing_key:
107
124
  specification_version: 4
108
125
  summary: Better error page for Rails and other Rack apps
@@ -110,6 +127,7 @@ test_files:
110
127
  - spec/better_errors/code_formatter_spec.rb
111
128
  - spec/better_errors/error_page_spec.rb
112
129
  - spec/better_errors/middleware_spec.rb
130
+ - spec/better_errors/raised_exception_spec.rb
113
131
  - spec/better_errors/repl/basic_spec.rb
114
132
  - spec/better_errors/repl/pry_spec.rb
115
133
  - spec/better_errors/repl/shared_examples.rb
@@ -117,4 +135,4 @@ test_files:
117
135
  - spec/better_errors/support/my_source.rb
118
136
  - spec/better_errors_spec.rb
119
137
  - spec/spec_helper.rb
120
- has_rdoc:
138
+ - spec/without_binding_of_caller.rb
@@ -1,21 +0,0 @@
1
- class Exception
2
- original_set_backtrace = instance_method(:set_backtrace)
3
-
4
- if BetterErrors.binding_of_caller_available?
5
- define_method :set_backtrace do |*args|
6
- unless Thread.current[:__better_errors_exception_lock]
7
- Thread.current[:__better_errors_exception_lock] = true
8
- begin
9
- @__better_errors_bindings_stack = binding.callers.drop(1)
10
- ensure
11
- Thread.current[:__better_errors_exception_lock] = false
12
- end
13
- end
14
- original_set_backtrace.bind(self).call(*args)
15
- end
16
- end
17
-
18
- def __better_errors_bindings_stack
19
- @__better_errors_bindings_stack || []
20
- end
21
- end