Skip to content

Commit

Permalink
Merge pull request #7 from UliKuch/add-global-on-error-behavior
Browse files Browse the repository at this point in the history
Add global on_error and on_warning options
  • Loading branch information
UliKuch authored Oct 27, 2021
2 parents a54e736 + a144c5d commit b83f902
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['2.5', '2.6', '2.7']
ruby: ['2.5', '2.6', '2.7', '3.0']
handler: ['nokogiri', 'ox', 'oga']
steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.5.1
3.0.1
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ group :development, :test do
gem 'simplecov', require: false, platforms: [:mri]
gem 'coveralls', require: false, platforms: [:mri]

gem 'activerecord', '~> 5.0.0'
gem 'activerecord', '~> 6.0'
gem 'nokogiri', '>= 1.8.2'
gem 'ox', '>= 2.10.0'
gem 'oga', '>= 2.15'
end

group :test do
gem 'sqlite3', '~> 1.3.13'
gem 'sqlite3', '~> 1.4.2'
end
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,25 @@ document determines the value assigned to the alias.

If an element is defined in the source but is blank (e.g., `<pubDate></pubDate>`), it is ignored, and non-empty one is picked.

## Parsing Errors
By default, there are no notification or exceptions on parsing errors and warnings. For Nokogiri and Ox, you can
specify a custom behavior by passing procs that receive a string:

```ruby
on_error = ->(error_string) { raise error_string }
on_warning = ->(warning_string) { raise warning_string }

feed = Atom.parse(xml, on_error, on_warning)
```

You can also use a global setting (e.g. in `config/initializers/saxophone.rb` when using Saxophone together
with Ruby on Rails):

```ruby
Saxophone.on_error = ->(error_string) { raise error_string }
Saxophone.on_warning = ->(warning_string) { raise warning_string }
```

## Contributing

1. Fork it
Expand Down
16 changes: 16 additions & 0 deletions lib/saxophone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ def self.handler=(handler)
@@handler = handler
end
end

def self.on_error
@@on_error ||= ->(_) {}
end

def self.on_error=(on_error_proc)
@@on_error = on_error_proc
end

def self.on_warning
@@on_warning ||= ->(_) {}
end

def self.on_warning=(on_warning_proc)
@@on_warning = on_warning_proc
end
end

# Try handlers
Expand Down
4 changes: 2 additions & 2 deletions lib/saxophone/sax_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def self.included(base)
base.extend(ClassMethods)
end

def parse(xml_input, on_error = ->(_){}, on_warning = ->(_){})
def parse(xml_input, on_error = Saxophone.on_error, on_warning = Saxophone.on_warning)
handler_klass = Saxophone.const_get("SAX#{Saxophone.handler.capitalize}Handler")

handler = handler_klass.new(self, on_error, on_warning)
Expand All @@ -15,7 +15,7 @@ def parse(xml_input, on_error = ->(_){}, on_warning = ->(_){})

module InstanceMethods
def initialize(attributes = {})
attributes.each do |name, value|
attributes&.each do |name, value|
send("#{name}=", value)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/saxophone/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Saxophone
VERSION = "1.0.0"
VERSION = "1.1.0"
end
88 changes: 88 additions & 0 deletions spec/saxophone/global_config_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe "Saxophone global configurations" do
before(:all) do
class A
include Saxophone
end
end

after(:all) do
Object.send(:remove_const, :A)
end

describe "handler config" do
after(:all) do
Saxophone.handler = :ox # restore default settings
end

context "with handler set to ox" do
before do
Saxophone.handler = :ox
end

it "uses ox as handler" do
expect(Saxophone.handler).to eq :ox
end
end

context "with handler set to oga" do
before do
Saxophone.handler = :oga
end

it "uses oga as handler" do
expect(Saxophone.handler).to eq :oga
end
end

context "with handler set to nokogiri" do
before do
Saxophone.handler = :nokogiri
end

it "uses nokogiri as handler" do
expect(Saxophone.handler).to eq :nokogiri
end
end

context "with handler set to some other value" do
it "raises error" do
expect { Saxophone.handler = :not_a_valid_handler }.to raise_error(LoadError)
end
end
end

describe "global on_error config" do
broken_xml = "<top><title>Te & st</title><b>Matched!</b><c>And Again</c></top>"
xml = "<top><title>Test</title><b>Matched!</b><c>And Again</c></top>"

context "not configured" do
it "does not raise exception on valid xml" do
expect { A.parse xml }.not_to raise_error
end

it "does not raise exception on broken xml" do
expect { A.parse broken_xml }.not_to raise_error
end
end

context "configured to raise exception" do
before(:all) do
Saxophone.on_error = ->(error_string) { raise error_string }
end

after(:all) do
Saxophone.on_error = ->(_) {} # restore default settings
end

it "does not raise exception on valid xml" do
expect { A.parse xml }.not_to raise_error
end

it "raises exception on broken xml" do
expect { A.parse broken_xml }.to raise_error(RuntimeError)
end
end
end
end

0 comments on commit b83f902

Please sign in to comment.