jerry 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.reek +2 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +11 -2
- data/.yardopts +8 -1
- data/Gemfile +0 -2
- data/Guardfile +16 -0
- data/README.md +93 -78
- data/Rakefile +20 -1
- data/bin/console +3 -0
- data/bin/guard +3 -0
- data/bin/rake +3 -0
- data/bin/setup +3 -0
- data/doc/multiple-configurations.md +51 -0
- data/jerry.gemspec +8 -3
- data/lib/jerry/class_provider.rb +30 -0
- data/lib/jerry/config.rb +64 -61
- data/lib/jerry/errors.rb +16 -0
- data/lib/jerry/version.rb +1 -1
- data/lib/jerry.rb +27 -39
- data/spec/class_provider_spec.rb +109 -0
- data/spec/config_spec.rb +152 -132
- data/spec/error_spec.rb +23 -0
- data/spec/examples_spec.rb +120 -0
- data/spec/fixtures/db_app.rb +17 -0
- data/spec/fixtures/house.rb +15 -0
- data/spec/fixtures/multi_db_app.rb +31 -0
- data/spec/fixtures/shopping_cart.rb +70 -0
- data/spec/fixtures/shopping_cart_config.rb +27 -0
- data/spec/jerry_spec.rb +45 -110
- data/spec/spec_helper.rb +3 -5
- metadata +117 -9
- data/spec/support/silence_warnings.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d97c357a390c069b18e9516ad1e5dac1fcdfea5
|
4
|
+
data.tar.gz: b33040e60cc83f2a481d0181c809e7b045ca96ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eae3155f70ebb6bfd88cd878f2e4dfbe95f042a23439504d185717dd4f20583ffe3ad209e65511d922be4a5e403af7a836ef1969cdd45bff8241685e064838b0
|
7
|
+
data.tar.gz: f4cb19e8c591ae15611d0d02e1d7c6a46ea9fb1071ef37a83e454d48622565f537f59b44f7d67bc7be13ef9c13453cb8010d0a5fc66d4639000863f817f394d8
|
data/.gitignore
CHANGED
@@ -20,7 +20,7 @@ build/
|
|
20
20
|
## Documentation cache and generated files:
|
21
21
|
/.yardoc/
|
22
22
|
/_yardoc/
|
23
|
-
/doc/
|
23
|
+
/html-doc/
|
24
24
|
/rdoc/
|
25
25
|
|
26
26
|
## Environment normalisation:
|
@@ -35,4 +35,3 @@ Gemfile.lock
|
|
35
35
|
|
36
36
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
37
37
|
.rvmrc
|
38
|
-
|
data/.reek
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/Gemfile
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
guard 'rake', task: 'default' do
|
2
|
+
watch 'Rakefile'
|
3
|
+
watch '.rspec'
|
4
|
+
watch '.rubocop.yml'
|
5
|
+
watch '.reek'
|
6
|
+
watch %r{^lib/}
|
7
|
+
watch %r{^spec/}
|
8
|
+
end
|
9
|
+
|
10
|
+
guard 'rake', task: 'doc' do
|
11
|
+
watch '.yardopts'
|
12
|
+
watch 'LICENSE.txt'
|
13
|
+
watch(/.+\.(md|markdown)/)
|
14
|
+
watch %r{^lib/}
|
15
|
+
watch %r{^doc/}
|
16
|
+
end
|
data/README.md
CHANGED
@@ -4,114 +4,129 @@ Jerry
|
|
4
4
|
[![Build Status](https://travis-ci.org/beraboris/jerry.svg?branch=master)](https://travis-ci.org/beraboris/jerry)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/beraboris/jerry/badge.png)](https://coveralls.io/r/beraboris/jerry)
|
6
6
|
|
7
|
-
Jerry
|
8
|
-
|
7
|
+
Jerry is a Ruby
|
8
|
+
[Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control)
|
9
|
+
container. You tell it how your classes depend on one another and it will create
|
10
|
+
your application and wire all the dependencies correctly.
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
Jerry aims to be simple and straight forward. It also aims to be out of your
|
13
|
+
way. Your classes don't need to know anything about jerry.
|
12
14
|
|
13
|
-
|
15
|
+
Why?
|
16
|
+
----
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) is a
|
19
|
+
great pattern for building loosely coupled applications. It allows you to build
|
20
|
+
isolated components that can be swapped around.
|
18
21
|
|
19
|
-
|
22
|
+
The problem with this pattern is that it leaves you with a bunch of classes that
|
23
|
+
you have to build and wire together yourself. Jerry does that for you.
|
20
24
|
|
21
|
-
|
25
|
+
Getting started
|
26
|
+
---------------
|
22
27
|
|
23
|
-
|
24
|
-
|
25
|
-
$ gem install jerry
|
28
|
+
### Important note
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
Currently jerry only supports constructor injection. If you're hoping to use
|
31
|
+
setter injection, you're out of luck. You're going to need to switch to
|
32
|
+
constructor injection.
|
29
33
|
|
30
|
-
|
34
|
+
### Install it
|
31
35
|
|
32
|
-
|
33
|
-
class Window; end
|
34
|
-
class Door; end
|
35
|
-
|
36
|
-
class House
|
37
|
-
attr_reader :window, :door
|
38
|
-
|
39
|
-
def initialize(window, door)
|
40
|
-
@window = window
|
41
|
-
@door = door
|
42
|
-
end
|
43
|
-
end
|
44
|
-
```
|
36
|
+
You have 3 options:
|
45
37
|
|
46
|
-
|
38
|
+
Options 1: Add jerry to your `Gemfile`
|
47
39
|
|
48
40
|
```ruby
|
49
|
-
|
41
|
+
gem 'jerry', '~> 2.0'
|
50
42
|
```
|
51
|
-
|
52
|
-
|
43
|
+
|
44
|
+
Option 2: Add jerry to your `*.gemspec`
|
53
45
|
|
54
46
|
```ruby
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
component(:house) { House.new rig(:window), rig(:door) }
|
47
|
+
Gem::Specification.new do |spec|
|
48
|
+
# ...
|
49
|
+
spec.add_dependency 'jerry', '~> 2.0'
|
59
50
|
end
|
60
51
|
```
|
61
52
|
|
62
|
-
|
63
|
-
build a component.
|
53
|
+
Option 3: Just install it
|
64
54
|
|
65
|
-
|
55
|
+
$ gem install jerry
|
56
|
+
|
57
|
+
### Create a configuration class
|
66
58
|
|
67
59
|
```ruby
|
68
|
-
jerry
|
69
|
-
house = jerry.rig :house
|
70
|
-
```
|
60
|
+
require 'jerry'
|
71
61
|
|
72
|
-
|
73
|
-
|
62
|
+
class MyConfig < Jerry::Config
|
63
|
+
def initialize(foo_db_url, bar_db_url)
|
64
|
+
@foo_db_url = foo_db_url
|
65
|
+
@bar_db_url = bar_db_url
|
66
|
+
end
|
74
67
|
|
75
|
-
|
76
|
-
`:single`. If you set the scope to `:single` only one instance of the component will be created. If you set it to
|
77
|
-
`:instance`, a new instance of the component will be created each time you call `rig`.
|
68
|
+
bind Application, [FooService, BarService]
|
78
69
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
70
|
+
singleton bind FooService, [BarService, :foo_db]
|
71
|
+
singleton bind BarService, [:bar_db]
|
72
|
+
|
73
|
+
named_bind :foo_db Database [proc { @foo_db_url }]
|
74
|
+
named_bind :bar_db Database [proc { @bar_db_url }]
|
83
75
|
end
|
84
|
-
|
76
|
+
```
|
85
77
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
78
|
+
Let's go over what's going on in this configuration class.
|
79
|
+
|
80
|
+
First, we define a constructor. It takes two database urls and stores them as
|
81
|
+
instance variables. We'll go over what these urls are used for later. You should
|
82
|
+
note that this constructor has no special meaning to jerry. It's entirely
|
83
|
+
specific to this configuration class.
|
84
|
+
|
85
|
+
Second, we use `bind` to tell jerry how to wire the `Application` class. `bind`
|
86
|
+
takes two arguments. The first is the class we're telling jerry about and the
|
87
|
+
second is an array that tells jerry what constructor arguments to pass to the
|
88
|
+
class. Here you can notice that `Application` takes an instance of `FooService`
|
89
|
+
and an instance of `BarService` in its constructor.
|
90
|
+
|
91
|
+
Third, we tell jerry how to build `FooService` and `BarService`. Note that we're
|
92
|
+
calling `singleton bind` instead of `bind` here. `singleton` is used to tell
|
93
|
+
jerry that we want it to only instantiate the class we just described only once.
|
94
|
+
When we use `singleton` jerry will always pass the same instance of the given
|
95
|
+
class as a constructor argument. This is useful when some of your classes have
|
96
|
+
a persistent state. In this case, the `BarService` instance passed to both
|
97
|
+
`Application` and `FooService` will be the exact same instance.
|
98
|
+
|
99
|
+
Finally, we tell jerry how to build two instances of the `Database` class. The
|
100
|
+
first instance is named `:foo_db` and the second is named `:bar_db`. We
|
101
|
+
reference these instances when telling jerry about `FooService` and
|
102
|
+
`BarService`. This is what `named_bind` is for. We should also note that the
|
103
|
+
last arguments of the `named_bind` calls each contain a proc. In this case, the
|
104
|
+
procs are used to inject the database urls for each database. In a more general
|
105
|
+
sense, the procs are used to pass settings to various classes.
|
106
|
+
|
107
|
+
### Create your application
|
90
108
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
109
|
+
```ruby
|
110
|
+
require 'jerry'
|
111
|
+
|
112
|
+
jerry = Jerry.new MyConfig.new('db://localhost/foo', 'db://localhost/bar')
|
113
|
+
app = jerry[Application]
|
95
114
|
```
|
96
115
|
|
97
|
-
|
98
|
-
----------------
|
116
|
+
Let's look at what's going on here.
|
99
117
|
|
100
|
-
|
101
|
-
|
118
|
+
First, we create an instance of our configuration class. We pass the urls for
|
119
|
+
our two databases to the constructor.
|
102
120
|
|
103
|
-
|
104
|
-
|
121
|
+
Second, we create an instance of `Jerry` passing in the instance of our
|
122
|
+
configuration class.
|
105
123
|
|
106
|
-
|
107
|
-
|
108
|
-
component(:thing) { "from a" }
|
109
|
-
end
|
110
|
-
class ConfB < Jerry::Config
|
111
|
-
component(:thing) { "from b" }
|
112
|
-
end
|
113
|
-
jerry = Jerry.new ConfA.new, ConfB.new
|
124
|
+
Finally, we use the square bracket operator (`[]`) to create an instance of our
|
125
|
+
application. Of course our application is wired properly.
|
114
126
|
|
115
|
-
|
116
|
-
|
117
|
-
|
127
|
+
Learn more
|
128
|
+
----------
|
129
|
+
|
130
|
+
If you'd like to learn more, here's some more documentation:
|
131
|
+
|
132
|
+
- [Multiple configurations](doc/multiple-configurations.md)
|
data/Rakefile
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
require 'reek/rake/task'
|
6
|
+
|
7
|
+
task default: [:spec, :lint]
|
3
8
|
|
4
9
|
RSpec::Core::RakeTask.new :spec
|
5
|
-
|
10
|
+
YARD::Rake::YardocTask.new :doc
|
11
|
+
|
12
|
+
task lint: [:reek, :rubocop]
|
13
|
+
|
14
|
+
desc 'Run rubocop linter on lib/**/*.rb and spec/**/*.rb'
|
15
|
+
RuboCop::RakeTask.new :rubocop do |t|
|
16
|
+
t.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
|
17
|
+
t.fail_on_error = false
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Run reek linter on lib/**/*.rb'
|
21
|
+
Reek::Rake::Task.new :reek do |t|
|
22
|
+
t.source_files = 'lib/**/*.rb'
|
23
|
+
t.fail_on_error = false
|
24
|
+
end
|
data/bin/console
ADDED
data/bin/guard
ADDED
data/bin/rake
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Multiple configurations
|
2
|
+
-----------------------
|
3
|
+
|
4
|
+
Jerry allows you to define and use multiple configurations. This way you can
|
5
|
+
separate the dependency configurations for different parts of your application.
|
6
|
+
|
7
|
+
Let's look at an example. In this example, we have a simple on-line store. It
|
8
|
+
has users, products and shopping carts. We can create separate configurations
|
9
|
+
for user, product, and shopping cart related classed. Users, products and
|
10
|
+
shopping carts each have a service that talks to the database and other services
|
11
|
+
and a controller that talks to the service. Here's what it might look like:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
class DatabaseConfig < Jerry::Config
|
15
|
+
# database connector thingy
|
16
|
+
bind Database
|
17
|
+
end
|
18
|
+
|
19
|
+
class UserConfig < Jerry::Config
|
20
|
+
bind UserService, [Database]
|
21
|
+
bind UserController, [UserService]
|
22
|
+
end
|
23
|
+
|
24
|
+
class ProductConfig < Jerry::Config
|
25
|
+
bind ProductService, [Database]
|
26
|
+
bind ProductController, [ProductService]
|
27
|
+
end
|
28
|
+
|
29
|
+
class ShoppingCartConfig < Jerry::Config
|
30
|
+
bind ShoppingCartService, [Database, ProductService, UserService]
|
31
|
+
bind ShoppingCartController, [ShoppingCartService]
|
32
|
+
end
|
33
|
+
|
34
|
+
class AppConfig < Jerry::Config
|
35
|
+
bind Application, [UserController, ProductController, ShoppingCartController]
|
36
|
+
end
|
37
|
+
|
38
|
+
jerry = Jerry.new(
|
39
|
+
DatabaseConfig.new,
|
40
|
+
AppConfig.new,
|
41
|
+
UserConfig.new,
|
42
|
+
ProductConfig.new,
|
43
|
+
ShoppingCartConfig.new
|
44
|
+
)
|
45
|
+
|
46
|
+
app = jerry[Application]
|
47
|
+
```
|
48
|
+
|
49
|
+
Note that in the example above, some the configurations reference classes that
|
50
|
+
are configured in other configurations. This is perfectly fine. When
|
51
|
+
instantiating a class, jerry will look at all the configurations.
|
data/jerry.gemspec
CHANGED
@@ -14,12 +14,17 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ['lib']
|
20
19
|
|
21
20
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
21
|
spec.add_development_dependency 'rake'
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency '
|
22
|
+
spec.add_development_dependency 'guard'
|
23
|
+
spec.add_development_dependency 'guard-rake'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
25
|
+
spec.add_development_dependency 'coveralls', '~> 0.8'
|
26
|
+
spec.add_development_dependency 'yard', '~> 0.8.7'
|
27
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.32'
|
29
|
+
spec.add_development_dependency 'reek', '~> 2.2'
|
25
30
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Jerry
|
2
|
+
# A provider that instanciates a given class by collecting constructor
|
3
|
+
# arguments through a given jerry instance.
|
4
|
+
class ClassProvider
|
5
|
+
# @param klass [Class] class to be instanciated
|
6
|
+
# @param args_spec [Array<Clsss, Symbol, Proc>] specification for the
|
7
|
+
# constructor arguments. Classes and Symbols are used to collect the
|
8
|
+
# arguments from the jerry instance. Procs are called to generate
|
9
|
+
# arguments.
|
10
|
+
def initialize(klass, args_spec)
|
11
|
+
@klass = klass
|
12
|
+
@args_spec = args_spec
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param jerry [Jerry] a jerry instance
|
16
|
+
# @param config [Jerry::Config] the config holding the provider
|
17
|
+
# @return An instance of the class given in the constructor
|
18
|
+
def call(jerry, config)
|
19
|
+
args = @args_spec.map do |spec|
|
20
|
+
if spec.respond_to? :call
|
21
|
+
config.instance_exec(jerry, config, &spec)
|
22
|
+
else
|
23
|
+
jerry[spec]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@klass.new(*args)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/jerry/config.rb
CHANGED
@@ -1,85 +1,88 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class ComponentError < StandardError; end
|
1
|
+
require 'jerry/class_provider'
|
2
|
+
require 'jerry/errors'
|
4
3
|
|
5
|
-
|
4
|
+
class Jerry
|
5
|
+
# A configuration specifies how to wire parts of an application
|
6
|
+
#
|
7
|
+
# @abstract Subclass this class in order to create a configuration
|
8
|
+
# @example Basic usage
|
9
|
+
# class Door; end
|
10
|
+
# class Window; end
|
6
11
|
#
|
7
|
-
#
|
8
|
-
#
|
12
|
+
# class House
|
13
|
+
# def initialize(door, window)
|
14
|
+
# # ...
|
15
|
+
# end
|
16
|
+
# end
|
9
17
|
#
|
10
|
-
# @abstract Subclass to define a config
|
11
|
-
# @example
|
12
18
|
# class MyConfig < Jerry::Config
|
13
|
-
#
|
14
|
-
#
|
19
|
+
# bind House, [Door, Window]
|
20
|
+
# bind Door
|
21
|
+
# bind Window
|
15
22
|
# end
|
16
23
|
class Config
|
17
24
|
class << self
|
18
|
-
#
|
19
|
-
|
20
|
-
|
25
|
+
# Specify how to wire the dependencies of a given class
|
26
|
+
#
|
27
|
+
# @param klass [Class] The class to wire the dependencies for
|
28
|
+
# @param ctor_args [Array<Class, Symbol, Proc>] specifies the arguments to
|
29
|
+
# be given to the constructor
|
30
|
+
# @return [Class] the class that will be instanciated
|
31
|
+
def bind(klass, ctor_args = [])
|
32
|
+
named_bind klass, klass, ctor_args
|
21
33
|
end
|
22
34
|
|
23
|
-
#
|
35
|
+
# Specify how to wire the dependencies of a given class giving it a name
|
24
36
|
#
|
25
|
-
# @param [Symbol]
|
26
|
-
#
|
27
|
-
# @
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
# @param name [Symbol] The name used to identify this way of building the
|
38
|
+
# given class
|
39
|
+
# @param klass [Class] The class to wire the dependencies for
|
40
|
+
# @param ctor_args [Array<Class, Symbol, Proc>] specifies the arguments to
|
41
|
+
# be given to the constructor
|
42
|
+
# @return [Symbol] the name of the class that will be instanciated
|
43
|
+
def named_bind(name, klass, ctor_args = [])
|
44
|
+
providers[name] = ClassProvider.new klass, ctor_args
|
45
|
+
name
|
46
|
+
end
|
35
47
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
# Specifies that a class should only be instanciated once
|
49
|
+
#
|
50
|
+
# @param key [Class, Symbol] the class or the name of the class that
|
51
|
+
# should only be instanciated once
|
52
|
+
def singleton(key)
|
53
|
+
return unless providers.key? key
|
40
54
|
|
41
|
-
|
42
|
-
case scope
|
43
|
-
when :single
|
44
|
-
cache[name] ||= instance_eval(&block)
|
45
|
-
when :instance
|
46
|
-
instance_eval(&block)
|
47
|
-
end
|
48
|
-
end
|
55
|
+
provider = providers[key]
|
49
56
|
|
50
|
-
|
57
|
+
instance = nil
|
58
|
+
providers[key] = ->(*args) { instance ||= provider.call(*args) }
|
51
59
|
end
|
52
|
-
end
|
53
60
|
|
54
|
-
|
55
|
-
|
56
|
-
|
61
|
+
def providers
|
62
|
+
@providers ||= {}
|
63
|
+
end
|
57
64
|
end
|
58
65
|
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# This gets set by Jerry when it loads a config
|
66
|
+
# The jerry instance this config is part of
|
62
67
|
attr_writer :jerry
|
63
68
|
|
64
|
-
|
69
|
+
# @return an instance of an object wired by the config
|
70
|
+
def [](key)
|
71
|
+
provider = self.class.providers[key]
|
65
72
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
# This should be used inside the block passed to Config::component
|
76
|
-
def knows?(component)
|
77
|
-
@jerry.knows? component
|
73
|
+
if provider
|
74
|
+
provider.call @jerry, self
|
75
|
+
else
|
76
|
+
fail InstantiationError,
|
77
|
+
"Failed to instanciate #{key}. Can't find provider for it"
|
78
|
+
end
|
79
|
+
rescue RuntimeError
|
80
|
+
raise InstantiationError, "Provider for #{key} raised an error"
|
78
81
|
end
|
79
82
|
|
80
|
-
#
|
81
|
-
def
|
82
|
-
|
83
|
+
# @return true if this config can provide the given key, false otherwise
|
84
|
+
def knows?(key)
|
85
|
+
self.class.providers.key? key
|
83
86
|
end
|
84
87
|
end
|
85
|
-
end
|
88
|
+
end
|
data/lib/jerry/errors.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'English'
|
2
|
+
|
3
|
+
class Jerry
|
4
|
+
# Base error class for Jerry that allows recording causing exceptions
|
5
|
+
class Error < RuntimeError
|
6
|
+
attr_reader :cause
|
7
|
+
|
8
|
+
def initialize(message = nil)
|
9
|
+
super
|
10
|
+
@cause = $ERROR_INFO
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Failed to instanciate a class
|
15
|
+
class InstantiationError < Jerry::Error; end
|
16
|
+
end
|
data/lib/jerry/version.rb
CHANGED