Skip to content

Commit

Permalink
Updated to add i18n interpolation support. Changed how metadata is su…
Browse files Browse the repository at this point in the history
…pplied and returned.
  • Loading branch information
Anthony Smith committed Nov 19, 2013
1 parent cc734ae commit 5dc7790
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 74 deletions.
78 changes: 58 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,37 @@ Before you can raise an error you'll need to register it first.
Errawr.register!(:your_error)
```

It's also possible to pass in additional metadata when registering an error.
### Raising Errors

```ruby
Errawr.register!(:bad_request, { http_status: 400 })
begin
Errawr.error!(:bad_request)
Errawr.error!(:your_error)
rescue => e
puts e.context[:http_status]
puts e.message # Localized error message defined in locale file
end
```

### Raising Errors
### Metadata

It's possible to add additional information to a registered error through metadata. Just specify a ```metadata``` hash when either registering:

```ruby
Errawr.register!(:your\_error, metadata: { http\_status: 400 })
begin
Errawr.error!(:your_error)
rescue => e
puts e.message # Localized error message defined in locale file
puts e.metadata[:http_status] # Will return 400
end
```

or throwing an error:

```ruby
Errawr.register!(:your_error)
begin
Errawr.error!(:your\_error, metadata: { http\_status: 400 })
rescue => e
puts e.metadata[:http_status] # Will return 400
end
```

Expand All @@ -73,9 +86,9 @@ It's also possible to manage your errors and their metadata purely through local
en:
errawr:
your_error:
name: my error
error:
message: My awesome error message
message: My awesome error message
metadata:
http_status: 400
```

Then just register and raise your exceptions like normal.
Expand All @@ -85,11 +98,29 @@ Errawr.register!(:your_error)
begin
Errawr.error!(:your_error)
rescue => e
puts e.context[:name] # Will return "my error"
puts e.metadata[:http_status] # Will return 400
end
```

**Note** the ```errawr.your_error.error.message``` locale key. This is the key used to define an error message when managing an error through a locale file.
### I18n Interpolation

You can pass in parameter values to your localized error messages.

```yaml
en
errawr:
your_error:
message: "My awesome error message is: %{error_message}"
```

```ruby
Errawr.register!(:your\_error, error\_message: 'You did it wrong!')
begin
Errawr.error!(:your_error)
rescue => e
puts e.message # Will return "My awesome error message is: You did it wrong!"
end
```

### Overrides

Expand All @@ -99,25 +130,32 @@ Want to override that metadata you registered? That's cool too.
en:
errawr:
your_error:
name: my error
error:
message: My awesome error message
message: My awesome error message
metadata:
http_status: 400
```

The ```#register!``` method will override the locale file.

```ruby
# #register! overrides metadata defined in the locale file
Errawr.register!(:your_error, name: 'my infamous error')
Errawr.register!(:your\_error, message: 'Some other error message', metadata: { http\_status: 403 })
begin
Errawr.error!(:your_error)
rescue => e
puts e.context[:name] # Will return "my infamous error"
puts e.message # => Will return "Some other error message"
puts e.metadata[:http_status] # => Will return 403
end
```

The ```#error!``` method will override both ```#register!``` and the locale file.

```ruby
Errawr.register!(:your\_error, message: 'Some other error message', metadata: { http\_status: 403 })
begin
# #error! metadata overrides both #register! and the locale file
Errawr.error!(:your_error, name: 'my very favorite error')
Errawr.error!(:your\_error, message: 'Yet another error message', metadata: { http\_status: 404 })
rescue => e
puts e.context[:name] # Will return "my very favorite error"
puts e.message # => Will return "Yet another error message"
puts e.metadata[:http_status] # => Will return 404
end
```

Expand Down
1 change: 1 addition & 0 deletions lib/errawr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Errawr

def self.error!(name, context = {})
klass = Mapper[name] || Mapper[:unknown]
klass.metadata.merge!(context.delete(:metadata) || {})
klass.context.merge!(context)
raise klass
end
Expand Down
16 changes: 12 additions & 4 deletions lib/errawr/error.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
module Errawr
class Error < StandardError
attr_reader :key, :context, :message
attr_reader :key, :context, :metadata, :message

def initialize(key = :unknown, context = {})
@key = key
@i18n = I18n.t('errawr.' + @key.to_s)
process_context(context)
process_metadata(context)
process_message
end

private
def process_context(context)
if @i18n.kind_of?(Hash)
@context = @i18n.merge(context)
@context.delete(:error)
@context.delete(:metadata)
else
@context = {}
end
end

def process_metadata(context)
if @i18n.kind_of?(Hash)
context = @i18n.merge(context)
end
@metadata = context.fetch(:metadata, {})
end

def process_message
if @i18n.kind_of?(Hash)
key = 'errawr.' + @key.to_s + '.error.message'
@message = I18n.t(key, @context, { default: I18n.t('errawr.unknown', @context) })
key = 'errawr.' + @key.to_s + '.message'
@message = I18n.t(key, @context.merge({ default: I18n.t('errawr.unknown', @context) }))
else
@message = I18n.t('errawr.' + @key.to_s, @context)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/errawr/mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ def self.add(error)
end

def self.register!(key, options = {})
base_klass = options[:error] ? options[:error][:base_class] || Error : Error
base_klass = options[:base_class] || Error
raise(ArgumentError, ':base_class must be a subclass of Errawr::Error') unless base_klass <= Error
klass = Class.new(base_klass).new(key, options.select { |k, v| ![:error].include?(k) })
klass = Class.new(base_klass).new(key, options)
add(klass)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/errawr/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Errawr
VERSION = '1.0.0'
VERSION = '1.1.0'
end
62 changes: 59 additions & 3 deletions spec/errawr_spec.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,64 @@
require 'spec_helper'

describe Errawr do
it 'should raise an Errawr::Error exception' do
Errawr.register!(:dummy_error)
expect { Errawr.error!(:dummy_error) }.to raise_error(Errawr::Error)
describe 'error!' do
it 'should raise an Errawr::Error exception' do
Errawr.register!(:dummy_error)
expect { Errawr.error!(:dummy_error) }.to raise_error(Errawr::Error)
end

it 'should return custom metadata values using #register!' do
Errawr.register!(:some_error, metadata: { name: 'custom_register!_name' })
begin
Errawr.error!(:some_error)
rescue => e
e.metadata[:name].should == 'custom_register!_name'
end
end

it 'should return custom metadata values using #error!' do
Errawr.register!(:some_error, metadata: { name: 'custom_register!_name' })
begin
Errawr.error!(:some_error, metadata: { name: 'custom_error!_name' })
rescue => e
e.metadata[:name].should == 'custom_error!_name'
end
end

it 'should return custom metadata values from locale file' do
Errawr.register!(:error_hash)
begin
Errawr.error!(:error_hash)
rescue => e
e.metadata.include?(:name).should be_true
end
end

it '#register! should override custom metadata values from locale file' do
Errawr.register!(:error_hash, metadata: { name: 'register!_name' })
begin
Errawr.error!(:error_hash)
rescue => e
e.metadata[:name].should == 'register!_name'
end
end

it 'should override custom metadata values from #register! and locale file' do
Errawr.register!(:error_hash, metadata: { name: 'register!_name' })
begin
Errawr.error!(:error_hash, metadata: { name: 'error!_name' })
rescue => e
e.metadata[:name].should == 'error!_name'
end
end

it 'should interpolate locales' do
Errawr.register!(:interpolated_error, error_message: 'interpolated message')
begin
Errawr.error!(:interpolated_error)
rescue => e
e.message.should == 'Some error has occurred: interpolated message'
end
end
end
end
7 changes: 1 addition & 6 deletions spec/error_spec.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
require 'spec_helper'

describe Errawr::Error do
before(:each) do
I18n.load_path += Dir.glob('spec/support/en.yml')
I18n.reload!
end

it 'should return a key of :unknown if no key is set' do
error = Errawr::Error.new
error.key.should == :unknown
Expand All @@ -28,6 +23,6 @@

it 'should insert custom values into the context if I18n value is a hash' do
error = Errawr::Error.new(:error_hash)
error.context[:name].should == 'error_name'
error.metadata[:name].should == 'error_name'
end
end
37 changes: 4 additions & 33 deletions spec/mapper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,20 @@

describe 'register!' do
it 'should throw an error if base class is not a subclass of Errawr::Error' do
expect { Errawr.register!(:dummy_error, { error: { base_class: StandardError } }) }.to raise_error(ArgumentError)
expect { Errawr.register!(:dummy_error, base_class: StandardError) }.to raise_error(ArgumentError)
end

it 'should add an error to stored errors' do
Errawr.register!(:dummy_error)
Errawr::Mapper[:dummy_error].should_not be_nil
end

it 'should not add :error options to context' do
Errawr.register!(:dummy_error, error: { name: :same_dummy_error })
it 'should not add :metadata options to context' do
Errawr.register!(:dummy_error, metadata: { name: :same_dummy_error })
begin
Errawr.error!(:dummy_error)
rescue => e
e.context.include?(:error).should be_false
end
end
end

describe 'error!' do
it 'should return custom context values from locale file' do
Errawr.register!(:error_hash)
begin
Errawr.error!(:error_hash)
rescue => e
e.context.include?(:name).should be_true
end
end

it '#register! should override custom context values from locale file' do
Errawr.register!(:error_hash, name: 'register!_name')
begin
Errawr.error!(:error_hash)
rescue => e
e.context[:name].should == 'register!_name'
end
end

it '#error! should override custom context values from #register! and locale file' do
Errawr.register!(:error_hash, name: 'register!_name')
begin
Errawr.error!(:error_hash, name: 'error!_name')
rescue => e
e.context[:name].should == 'error!_name'
e.metadata.include?(:error).should be_false
end
end
end
Expand Down
9 changes: 8 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@

# Require supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| puts f; require f }
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| puts f; require f }

RSpec.configure do |config|
config.before(:each) do
I18n.load_path += Dir.glob('spec/support/en.yml')
I18n.reload!
end
end
11 changes: 7 additions & 4 deletions spec/support/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ en:
errawr:
some_error: Some error has occurred
error_hash:
name: error_name
error:
message: Some hashed error has occurred
message: Some hashed error has occurred
metadata:
name: error_name
bad_error_hash:
name: bad_error
metadata:
name: bad_error
interpolated_error:
message: "Some error has occurred: %{error_message}"

0 comments on commit 5dc7790

Please sign in to comment.