readable_exceptions 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +76 -0
- data/Rakefile +2 -0
- data/lib/readable_exceptions.rb +58 -0
- data/lib/readable_exceptions/version.rb +3 -0
- data/readable_exceptions.gemspec +23 -0
- data/spec/empty.yml +0 -0
- data/spec/example.yml +12 -0
- data/spec/readable_exceptions_spec.rb +124 -0
- data/spec/spec_helper.rb +2 -0
- metadata +90 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
Given a configured exception type and error context, returns a human readable error message.
|
4
|
+
|
5
|
+
# Configure it
|
6
|
+
|
7
|
+
Create your configuration file, readable_exceptions.yml.
|
8
|
+
|
9
|
+
"WallPostException":
|
10
|
+
wall_context: "We can not post to your wall"
|
11
|
+
friend_wall_context: "We can not post to your friends wall"
|
12
|
+
|
13
|
+
"WallPostException::IntermittentError":
|
14
|
+
wall_context: "We can not post to your wall right now. We'll try again later."
|
15
|
+
|
16
|
+
WallPostException::IntermittentError is a child class of WallPostException.
|
17
|
+
|
18
|
+
# Use it
|
19
|
+
|
20
|
+
ReadableExceptions.setup(File.dirname(__FILE__) + "/readable_exceptions.yml")
|
21
|
+
|
22
|
+
begin
|
23
|
+
post_to_wall()
|
24
|
+
rescue WallPostException => e
|
25
|
+
puts e.readable_message(:wall_context) # puts "We can not post to your wall"
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
post_to_friends_wall()
|
30
|
+
rescue WallPostException => e
|
31
|
+
puts e.readable_message(:friend_wall_context) # puts "We can not post to your friends wall"
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
post_to_wall()
|
36
|
+
rescue WallPostException::IntermittentError => e
|
37
|
+
puts e.readable_message(:wall_context) # puts "We can not post to your wall right now. We'll try again later."
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
post_to_friends_wall()
|
42
|
+
rescue WallPostException::IntermittentError => e
|
43
|
+
puts e.readable_message(:friend_wall_context) # puts "We can not post to your friends wall"
|
44
|
+
end
|
45
|
+
|
46
|
+
begin
|
47
|
+
raise WallPostException, :wall_context
|
48
|
+
rescue StandardError => e
|
49
|
+
puts e.readable_message # puts "We can not post to your wall"
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
raise WallPostException, :friend_wall_context
|
54
|
+
rescue StandardError => e
|
55
|
+
puts e.readable_message # puts "We can not post to your friends wall"
|
56
|
+
end
|
57
|
+
|
58
|
+
begin
|
59
|
+
raise WallPostException::IntermittentError, :wall_context
|
60
|
+
rescue StandardError => e
|
61
|
+
puts e.readable_message # puts "We can not post to your wall right now. We'll try again later."
|
62
|
+
end
|
63
|
+
|
64
|
+
begin
|
65
|
+
raise WallPostException::IntermittentError, :friend_wall_context
|
66
|
+
rescue StandardError => e
|
67
|
+
puts e.readable_message # puts "We can not post to your friends wall"
|
68
|
+
end
|
69
|
+
|
70
|
+
begin
|
71
|
+
raise UnconfiguredException, :wall_context
|
72
|
+
rescue StandardError => e
|
73
|
+
puts e.readable_message # puts e.message
|
74
|
+
end
|
75
|
+
|
76
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module ReadableExceptions
|
4
|
+
|
5
|
+
def self.setup(readable_msgs_file_path)
|
6
|
+
@@error_messages = parse_input(readable_msgs_file_path)
|
7
|
+
|
8
|
+
Exception.class_eval do
|
9
|
+
def readable_message(context = nil)
|
10
|
+
::ReadableExceptions::readable_message(self, context)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.readable_message(exception, context = nil)
|
16
|
+
context ||= exception.message
|
17
|
+
return exception.message if ! valid_context?(context)
|
18
|
+
|
19
|
+
readable_message = message_for_context(exception.class, context)
|
20
|
+
return exception.message if readable_message.nil?
|
21
|
+
|
22
|
+
readable_message
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.error_messages
|
28
|
+
@@error_messages
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.parse_input(readable_msgs_file_path)
|
32
|
+
raise(ArgumentError, "Input file must be a readable") unless (File.readable?(readable_msgs_file_path) rescue false)
|
33
|
+
|
34
|
+
error_messages = (YAML::load(IO.read(readable_msgs_file_path))) rescue false
|
35
|
+
raise(ArgumentError, "Input file must be valid YAML") unless error_messages
|
36
|
+
|
37
|
+
error_messages
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.valid_context?(context)
|
41
|
+
context.kind_of?(Hash) && context.size == 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.message_for_context(klass, context)
|
45
|
+
return nil if klass.nil?
|
46
|
+
|
47
|
+
context_key = context.first[0].to_s
|
48
|
+
sub_context_key = context.first[1].to_s
|
49
|
+
klass_name = klass.name.to_s
|
50
|
+
|
51
|
+
if error_messages.has_key?(context_key) && error_messages[context_key].has_key?(klass_name) && error_messages[context_key][klass_name].has_key?(sub_context_key)
|
52
|
+
return error_messages[context_key][klass_name][sub_context_key]
|
53
|
+
end
|
54
|
+
|
55
|
+
message_for_context(klass.superclass, context)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "readable_exceptions/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "readable_exceptions"
|
7
|
+
s.version = ReadableExceptions::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Chad Krsek"]
|
10
|
+
s.email = ["chad@contextoptional.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Easily configure human readable error messages for your exception classes, or for classses declared in libraries you use.}
|
13
|
+
s.description = %q{Easily configure human readable error messages for your exception classes, or for classses declared in libraries you use.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "readable_exceptions"
|
16
|
+
|
17
|
+
s.add_dependency "rspec"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
data/spec/empty.yml
ADDED
File without changes
|
data/spec/example.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
foo:
|
2
|
+
"An::Exception":
|
3
|
+
input_context: "There has been an input failure"
|
4
|
+
output_context: "There has been an output failure"
|
5
|
+
|
6
|
+
bar:
|
7
|
+
"Another::Exception":
|
8
|
+
print_context: "We can not print right now"
|
9
|
+
post_context: "We can not post right now"
|
10
|
+
|
11
|
+
"ChildException":
|
12
|
+
print_context: "We can print right now"
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
# Declare classes that appear in yml input files
|
5
|
+
class An
|
6
|
+
class Exception < Exception
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Another
|
11
|
+
class Exception < Exception
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ChildException < Another::Exception
|
16
|
+
end
|
17
|
+
|
18
|
+
class YetAnother
|
19
|
+
class Exception < Exception
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
describe ReadableExceptions do
|
25
|
+
|
26
|
+
describe "should raise an exception when" do
|
27
|
+
|
28
|
+
it "input file is unreadable" do
|
29
|
+
lambda { ReadableExceptions.setup("") }.should raise_exception(ArgumentError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "input file is empty" do
|
33
|
+
lambda { ReadableExceptions.setup(File.dirname(__FILE__) + "/empty.yml") }.should raise_exception(ArgumentError)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "parses the input file" do
|
39
|
+
|
40
|
+
before :each do
|
41
|
+
ReadableExceptions.setup(File.dirname(__FILE__) + "/example.yml")
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "returns the exception's message when" do
|
45
|
+
|
46
|
+
it "has no readable message context" do
|
47
|
+
e = An::Exception.new("test")
|
48
|
+
e.readable_message.should == "test"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "the exception type does not have a readable message defined" do
|
52
|
+
e = YetAnother::Exception.new("test")
|
53
|
+
e.readable_message(:unknown => :context).should == "test"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "the exception has a readable message defined but not in this context" do
|
57
|
+
e = An::Exception.new("test")
|
58
|
+
e.readable_message(:foo => :context).should == "test"
|
59
|
+
e = An::Exception.new("test")
|
60
|
+
e.readable_message(:baz => :input_context).should == "test"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "neither the exception nor its parents have readable message defined for this context" do
|
64
|
+
e = ChildException.new("test")
|
65
|
+
e.readable_message(:unknown => :context).should == "test"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "returns the exception's readable message when" do
|
71
|
+
|
72
|
+
it "readable_message is called" do
|
73
|
+
An::Exception.new.readable_message.should == An::Exception.new.message
|
74
|
+
An::Exception.new.readable_message(:foo => :input_context).should == "There has been an input failure"
|
75
|
+
An::Exception.new.readable_message(:foo => :output_context).should == "There has been an output failure"
|
76
|
+
Another::Exception.new.readable_message(:bar => :print_context).should == "We can not print right now"
|
77
|
+
ChildException.new.readable_message(:bar => :print_context).should == "We can print right now"
|
78
|
+
Another::Exception.new.readable_message(:bar => :post_context).should == "We can not post right now"
|
79
|
+
ChildException.new.readable_message(:bar => :post_context).should == "We can not post right now"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "an exception is instantiated with its message set to a readable message key" do
|
83
|
+
begin
|
84
|
+
raise An::Exception, :foo => :input_context
|
85
|
+
rescue Exception => e
|
86
|
+
e.readable_message.should == "There has been an input failure"
|
87
|
+
end
|
88
|
+
|
89
|
+
begin
|
90
|
+
raise An::Exception, :foo => :output_context
|
91
|
+
rescue Exception => e
|
92
|
+
e.readable_message.should == "There has been an output failure"
|
93
|
+
end
|
94
|
+
|
95
|
+
begin
|
96
|
+
raise Another::Exception, :bar => :print_context
|
97
|
+
rescue Exception => e
|
98
|
+
e.readable_message.should == "We can not print right now"
|
99
|
+
end
|
100
|
+
|
101
|
+
begin
|
102
|
+
raise ChildException, :bar => :print_context
|
103
|
+
rescue Exception => e
|
104
|
+
e.readable_message.should == "We can print right now"
|
105
|
+
end
|
106
|
+
|
107
|
+
begin
|
108
|
+
raise Another::Exception, :bar => :post_context
|
109
|
+
rescue Exception => e
|
110
|
+
e.readable_message.should == "We can not post right now"
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
raise ChildException, :bar => :post_context
|
115
|
+
rescue Exception => e
|
116
|
+
e.readable_message.should == "We can not post right now"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: readable_exceptions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Chad Krsek
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-20 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
description: Easily configure human readable error messages for your exception classes, or for classses declared in libraries you use.
|
34
|
+
email:
|
35
|
+
- chad@contextoptional.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- Gemfile
|
45
|
+
- README.md
|
46
|
+
- Rakefile
|
47
|
+
- lib/readable_exceptions.rb
|
48
|
+
- lib/readable_exceptions/version.rb
|
49
|
+
- readable_exceptions.gemspec
|
50
|
+
- spec/empty.yml
|
51
|
+
- spec/example.yml
|
52
|
+
- spec/readable_exceptions_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: ""
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project: readable_exceptions
|
82
|
+
rubygems_version: 1.3.7
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Easily configure human readable error messages for your exception classes, or for classses declared in libraries you use.
|
86
|
+
test_files:
|
87
|
+
- spec/empty.yml
|
88
|
+
- spec/example.yml
|
89
|
+
- spec/readable_exceptions_spec.rb
|
90
|
+
- spec/spec_helper.rb
|