Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow skipping variable inspection by class name #449

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ See [the wiki for instructions on configuring the editor](https://github.com/Bet
BetterErrors.maximum_variable_inspect_size = 100_000
```

## Ignore inspection of variables with certain classes.

```ruby
# e.g. in config/initializers/better_errors.rb
# This will stop BetterErrors from trying to inspect objects of these classes, which can cause
# slow loading times and unneccessary database queries. Does not check inheritance chain, use
# strings not contants.
# default value: ['ActionDispatch::Request', 'ActionDispatch::Response']
BetterErrors.ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']
```

## Get in touch!

Expand Down
5 changes: 5 additions & 0 deletions lib/better_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@ class << self
# the variable won't be returned.
# @return int
attr_accessor :maximum_variable_inspect_size

# List of classes that are excluded from inspection.
# @return [Array]
attr_accessor :ignored_classes
end
@ignored_instance_variables = []
@maximum_variable_inspect_size = 100_000
@ignored_classes = ['ActionDispatch::Request', 'ActionDispatch::Response']

# Returns a proc, which when called with a filename and line number argument,
# returns a URL to open the filename and line in the selected editor.
Expand Down
8 changes: 7 additions & 1 deletion lib/better_errors/error_page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ def text_heading(char, str)
end

def inspect_value(obj)
InspectableValue.new(obj).to_html
if BetterErrors.ignored_classes.include? obj.class.name
"<span class='unsupported'>(Instance of ignored class. "\
"#{obj.class.name ? "Remove #{CGI.escapeHTML(obj.class.name)} from" : "Modify"}"\
" BetterErrors.ignored_classes if you need to see it.)</span>"
else
InspectableValue.new(obj).to_html
end
rescue BetterErrors::ValueLargerThanConfiguredMaximum
"<span class='unsupported'>(Object too large. "\
"#{obj.class.name ? "Modify #{CGI.escapeHTML(obj.class.name)}#inspect or a" : "A"}"\
Expand Down
54 changes: 49 additions & 5 deletions spec/better_errors/error_page_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require "spec_helper"

class ErrorPageTestIgnoredClass; end

module BetterErrors
describe ErrorPage do
# It's necessary to use HTML matchers here that are specific as possible.
Expand Down Expand Up @@ -45,28 +47,70 @@ module BetterErrors

it "shows local variables" do
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables') do
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: 'local_a')
with_tag('pre', text: ':value_for_local_a')
end
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: 'local_b')
with_tag('pre', text: ':value_for_local_b')
end
end

it "shows instance variables" do
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables') do
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@inst_c')
with_tag('pre', text: ':value_for_inst_c')
end
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@inst_d')
with_tag('pre', text: ':value_for_inst_d')
end
end

context 'when ignored_classes includes the class name of a local variable' do
before do
allow(BetterErrors).to receive(:ignored_classes).and_return(['ErrorPageTestIgnoredClass'])
end

let(:exception_binding) {
local_a = :value_for_local_a
local_b = ErrorPageTestIgnoredClass.new

@inst_c = :value_for_inst_c
@inst_d = ErrorPageTestIgnoredClass.new

binding
}

it "does not include that value" do
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: 'local_a')
with_tag('pre', text: ':value_for_local_a')
end
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: 'local_b')
with_tag('.unsupported', text: /Instance of ignored class/)
with_tag('.unsupported', text: /BetterErrors\.ignored_classes/)
end
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@inst_c')
with_tag('pre', text: ':value_for_inst_c')
end
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@inst_d')
with_tag('.unsupported', text: /Instance of ignored class/)
with_tag('.unsupported', text: /BetterErrors\.ignored_classes/)
end
end
end

it "does not show filtered variables" do
allow(BetterErrors).to receive(:ignored_instance_variables).and_return([:@inst_d])
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables') do
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@inst_c')
with_tag('pre', text: ':value_for_inst_c')
end
Expand Down Expand Up @@ -149,7 +193,7 @@ def initialize

it "does not attempt to show the class name" do
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables') do
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@big_anonymous')
with_tag('.unsupported', text: /Object too large/)
with_tag('.unsupported', text: /Adjust BetterErrors.maximum_variable_inspect_size/)
Expand Down Expand Up @@ -235,7 +279,7 @@ def initialize

it "does not attempt to show the class name" do
html = error_page.do_variables("index" => 0)[:html]
expect(html).to have_tag('div.variables') do
expect(html).to have_tag('div.variables tr') do
with_tag('td.name', text: '@big_anonymous')
with_tag('.unsupported', text: /Object too large/)
with_tag('.unsupported', text: /Adjust BetterErrors.maximum_variable_inspect_size/)
Expand Down