lab42_ihash 0.0.1.beta

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 340ee6217f0f1fabdcc7d5af631fe6c40982b6e9
4
+ data.tar.gz: ec83fb030f1ae017e193525fcedae4c8e335606b
5
+ SHA512:
6
+ metadata.gz: 90f46bf55fb52af4d0d6deda21421d66e2f530c2f27869a8f2348eb48160387f35ce15fb1af1f83e9e529af76258013836367eb98aebf23ac9d711c150fee9fd
7
+ data.tar.gz: 1f67e0a1699424b0e0e45a21fe740cadb0e0db02e5cc94420c7ca7562cc0ad10ec90417468fe82c678120f66888286a54d441e92805ac021bf5769b09a7b8176
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ # Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
35
+ .tmux
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format documentation
3
+ --tag ~js
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lab42_intellihash (0.0.1)
5
+ forwarder2 (~> 0.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ae (1.8.2)
11
+ ansi
12
+ ansi (1.4.3)
13
+ brass (1.2.1)
14
+ coderay (1.1.0)
15
+ diff-lcs (1.2.5)
16
+ facets (2.9.3)
17
+ forwarder2 (0.2.0)
18
+ method_source (0.8.2)
19
+ pry (0.9.12.6)
20
+ coderay (~> 1.0)
21
+ method_source (~> 0.8)
22
+ slop (~> 3.4)
23
+ pry-nav (0.2.3)
24
+ pry (~> 0.9.10)
25
+ qed (2.9.1)
26
+ ansi
27
+ brass
28
+ facets (>= 2.8)
29
+ rspec (2.14.1)
30
+ rspec-core (~> 2.14.0)
31
+ rspec-expectations (~> 2.14.0)
32
+ rspec-mocks (~> 2.14.0)
33
+ rspec-core (2.14.8)
34
+ rspec-expectations (2.14.5)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.14.6)
37
+ slop (3.5.0)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ ae (~> 1.8)
44
+ bundler (~> 1.6)
45
+ lab42_intellihash!
46
+ pry (~> 0.9)
47
+ pry-nav (~> 0.2)
48
+ qed (~> 2.9)
49
+ rspec (~> 2.14)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Robert Dober
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # lab42_ihash
2
+
3
+ A Hash with Business Logic ( call it intelligent ).
4
+
5
+ Actually it is a view layer over a Hash like object, which needs to obey the simple protocol
6
+
7
+ `Hash#fetch`.
8
+
9
+
10
+ The services `IHash` provides are of the number of four:
11
+
12
+ * Default values per key.
13
+ * Validation via _Constraints_.
14
+ * Business Logic or Lookup Logic.
15
+ * Caching of Computed Values.
16
+
17
+
18
+ ## Installation
19
+
20
+ ```sh
21
+ gem install lab42_ihash --pre
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ```ruby
27
+ require 'lab42/ihash'
28
+
29
+ IHash = Lab42::IHash
30
+ ```
31
+
32
+
33
+ ## Manual (QED Driven)
34
+
35
+ Details are explained in the [QED](https://github.com/rubyworks/qed) demos [here](https://github.com/RobertDober/lab42_intellihash/tree/master/demo)
@@ -0,0 +1,109 @@
1
+ # IHash QED
2
+
3
+ ## Introduction
4
+
5
+ An `IHash` is an object that lets us define an _intelligent_ way to access a Hash like object.
6
+
7
+
8
+ The services `IHash` provides are of the number of four:
9
+
10
+ * Default values per key.
11
+ * Validation via _Constraints_.
12
+ * Business Logic or Lookup Logic.
13
+ * Caching of Computed Values.
14
+
15
+ ## Defaults
16
+
17
+
18
+ ### Predefined
19
+
20
+ The simplest meaningful example could look like the following:
21
+
22
+ ```ruby
23
+ ihash = IHash.new a: 1, b: 2
24
+
25
+ ihash.get( :a ).assert == 1
26
+ ihash.get( :b ).assert == 2
27
+ ihash.set_values a: 42
28
+ ihash.get( :a ).assert == 42
29
+ # Defaults are not changed:
30
+ ihash.get( :b ).assert == 2
31
+ ```
32
+
33
+ Alternatively the `set_defaults` method can be used:
34
+
35
+ ```ruby
36
+ ihash.set_defaults a: 1, c: 2
37
+ # values are not touched
38
+ ihash.get( :a ).assert == 42
39
+ # new default values are in place
40
+ ihash.get( :c ).assert == 2
41
+ # But the old defaults have been lost
42
+ KeyError.assert.raised? do
43
+ ihash.get :b
44
+ end
45
+ ```
46
+
47
+ ### Defaults provided via a parameter
48
+
49
+ ```ruby
50
+ ihash = IHash.new a: 1
51
+
52
+ ihash.get( :a ).assert == 1
53
+ ihash.get( :a, 42 ).assert == 42
54
+
55
+ # However values override the default of course
56
+ ihash.set_values a: 2
57
+ ihash.get( :a, 42 ).assert == 2
58
+
59
+ ```
60
+
61
+
62
+ ### Computed Defaults
63
+
64
+ They are the main reason for caching, but as defaults provided
65
+ via parameters override cached values, we will need an alternative
66
+ calculation mechanisme for business logic, which we will discuss
67
+ later on.
68
+
69
+ For know all we need to know to understand the following example
70
+ is that `Proc` instances as default values will be evaluated
71
+ in the `IHash` instance's context.
72
+
73
+ ```ruby
74
+ rectangle = IHash.new \
75
+ height: ->{ get( :surface ) / get( :width ) },
76
+ width: ->{ get( :surface ) / get( :height ) },
77
+ surface: ->{ get( :width ) * get( :height ) }
78
+
79
+ # Obviously we need some data here. The following code
80
+ # will consume the whole stack before crashing.
81
+ # Later on we will see how to avoid this by means
82
+ # of defaults and constraints, and hopefully a later version
83
+ # of IHash will detect the mutual infinite recursion.
84
+
85
+ # rectangle.get :surface
86
+
87
+ # So let us provide some data
88
+ rectangle.set_values width: 20, height: 30
89
+ rectangle.get( :surface ).assert == 600
90
+ ```
91
+
92
+ Now it would be nice if we could avoid the potential stack overflow
93
+ by means of defaults.
94
+ And, as promised, we can:
95
+
96
+ ```ruby
97
+
98
+ rectangle = IHash.new \
99
+ height: ->{ get( :surface, 600 ) / get( :width, 20 ) },
100
+ width: ->{ get( :surface, 600 ) / get( :height ) },
101
+ surface: ->{ get( :width ) * get( :height ) }
102
+
103
+ # These defaults shall be sufficent
104
+ rectangle.get( :surface ).assert == 600
105
+ # and they are.
106
+
107
+ ```
108
+
109
+ To see how to do this with constraints, please refer to the [constraints demo](https://github.com/RobertDober/lab42_intellihash/blob/master/demo/050-constraints.md)
@@ -0,0 +1,70 @@
1
+ # IHash QED
2
+
3
+ ## Constraints
4
+
5
+ Constraints are evaluated whenever the values of an `IHash` instance are set via the `set_values` method.
6
+
7
+ The result of this evaluation is stored for later validation.
8
+
9
+ Let us dive into a simple example:
10
+
11
+ ```ruby
12
+ ihash = IHash.new
13
+ .set_constraints(
14
+ a: ->(eventual_value_for_a){ eventual_value_for_a == 42 } )
15
+ .set_values a: 43
16
+
17
+ ihash.valid?.assert == false
18
+ ihash.errors.empty?.assert == false
19
+ ihash.errors.first.assert =~ /value error for key :a and value 43/
20
+
21
+ ihash.set_values a: 42
22
+ ihash.valid?.assert == true
23
+ ihash.errors.empty?.assert == true
24
+
25
+ ```
26
+
27
+ In order to implement an early failure policy you need to raise exceptions yourself.
28
+
29
+ ```ruby
30
+ ArgumentError.assert.raised? do
31
+ ihash =
32
+ IHash.new
33
+ .set_constraints\
34
+ a: ->(value){ value == 42 or raise ArgumentError }
35
+
36
+ ihash.set_values a: 41
37
+ end
38
+ ```
39
+
40
+ Maybe a `set_constraints!` method doing something like that for you can be
41
+ implemented later on.
42
+
43
+ Oh and I am so glad you asked, before setting values, constraints are not enforced and
44
+ the instance is therefore valid in all cases:
45
+
46
+ ```ruby
47
+ ihash = IHash.new( a: nil ).set_constraints a: ->{ raise ArgumentError }
48
+
49
+ ihash.valid?.assert == true
50
+
51
+ ArgumentError.assert.raised? do
52
+ ihash.set_values b: nil
53
+ end
54
+ ihash.valid?.assert == false
55
+ ihash.errors.first.assert == 'constraint for key :a raised an error ArgumentError'
56
+ ```
57
+
58
+ And this works for calculated values too, of course:
59
+
60
+ ```ruby
61
+ ihash = IHash
62
+ .new( a: ->{ - get( :b ) } )
63
+ .set_constraints( a: ->(val){ val > 0 } )
64
+ .set_values b: 42
65
+
66
+ ihash.valid?.assert == false
67
+
68
+ ```
69
+
70
+
@@ -0,0 +1,12 @@
1
+ # IHash QED
2
+
3
+ ## Business Logic
4
+
5
+ _Not implemented_
6
+
7
+ For the time being the defaults semantics serve all YHS' needs. But he believes
8
+ that more complex computations, recursion detection, a seperate cache that
9
+ would override default parameters and other subtle differences might come forth
10
+ one day.
11
+
12
+
@@ -0,0 +1,77 @@
1
+ # IHash QED
2
+
3
+ ## Caching
4
+
5
+ Will only occur when lookup values or default values are accessed.
6
+
7
+ Actually `#cache` is exposed as an attribute, but manipulate it not (or at your
8
+ own risk).
9
+
10
+ ```ruby
11
+ ihash = IHash.new \
12
+ a: ->{ 42 },
13
+ b: 42
14
+
15
+ # The cache is empty
16
+ ihash.cache.assert.empty?
17
+
18
+ # Let us access :b
19
+ ihash.get :b
20
+ # The cache is not empty any more
21
+ ihash.cache.refute.empty?
22
+ # It has been filled with :b only
23
+ ihash.cache.assert.has_key? :b
24
+ ihash.cache.refute.has_key? :a
25
+ # And now we add :a
26
+ ihash.get :a
27
+ ihash.cache.assert.has_key? :b
28
+ ihash.cache.assert.has_key? :a
29
+
30
+ ```
31
+
32
+ ### Setting values invalidates the cache
33
+
34
+ ```ruby
35
+ ihash.set_values b: 56
36
+
37
+ # Cache is empty again
38
+ ihash.cache.assert.empty?
39
+ # Values come before the cache, but don't do that
40
+ ihash.cache[ :b ] = 22
41
+ ihash.get( :b ).assert == 56
42
+ # We did not even break anything
43
+ ihash.get( :a ).assert == 42
44
+ ihash.cache.assert.has_key? :a
45
+
46
+ ```
47
+
48
+ ### Value access does not populate the cache
49
+
50
+ ```ruby
51
+ ihash.set_values b: 29
52
+
53
+ ihash.cache.assert.empty?
54
+ ihash.get( :b ).assert == 29
55
+ ihash.cache.assert.empty?
56
+ ```
57
+
58
+
59
+ ### Setting defaults invalidates the cache too
60
+
61
+ ```ruby
62
+ ihash.get :a
63
+ ihash.cache.keys.assert == [:a]
64
+ ihash.set_defaults
65
+ # The following is not very wise, maybe setting values, defaults
66
+ # or constraints will reset the instance.
67
+ # Not sure: ihash.get( :b ).assert == 29
68
+ ihash.cache.assert.empty?
69
+
70
+ ```
71
+
72
+
73
+ This behavior might change with minor version updates as it is not very
74
+ intuitive.
75
+
76
+ Now that we are aware how caching and default values work let us go further with constraints
77
+
@@ -0,0 +1 @@
1
+ require 'ae'
@@ -0,0 +1,4 @@
1
+ LIBRARY_PATH = File.expand_path '../../lib'
2
+
3
+ require 'lab42/ihash'
4
+ IHash = Lab42::IHash
@@ -0,0 +1,37 @@
1
+
2
+ base = File.dirname __FILE__
3
+ $:.unshift File.join( base, 'lib' )
4
+
5
+ require 'lab42/ihash/version'
6
+
7
+ Gem::Specification.new do | spec |
8
+ spec.name = 'lab42_ihash'
9
+ spec.version = Lab42::IHash::VERSION
10
+ spec.authors = ['Robert Dober']
11
+ spec.email = %w{ robert.dober@gmail.com }
12
+ spec.description = %{A Hash with Business Logic (call it intelligent).}
13
+ spec.summary = %{A view over Hash like objects (needs to implement #fetch only).
14
+ Allowing to specify defaults, constraints and business logic. Implements caching for computed values.}
15
+ spec.homepage = %{https://github.com/RobertDober/lab42_ihash}
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.test_files = spec.files.grep(%r{\Atest|\Aspec|\Afeatures|\Ademo/})
20
+ spec.require_paths = %w{lib}
21
+
22
+ # spec.post_install_message = %q{ }
23
+
24
+
25
+ spec.required_ruby_version = '>= 2.0.0'
26
+ spec.required_rubygems_version = '>= 2.2.2'
27
+
28
+ # spec.add_dependency 'forwarder2', '~> 0.2'
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.6'
31
+ spec.add_development_dependency 'rspec', '~> 2.14'
32
+ spec.add_development_dependency 'pry', '~> 0.9'
33
+ spec.add_development_dependency 'pry-nav', '~> 0.2'
34
+ spec.add_development_dependency 'ae', '~> 1.8'
35
+ spec.add_development_dependency 'qed', '~> 2.9'
36
+
37
+ end
@@ -0,0 +1,5 @@
1
+ module Lab42
2
+ class IHash
3
+ VERSION = '0.0.1.beta'
4
+ end # class IHash
5
+ end # module Lab42
@@ -0,0 +1,89 @@
1
+ module Lab42
2
+ class IHash
3
+ attr_reader :cache, :constraints, :defaults, :errors, :values
4
+
5
+ def get key, *default
6
+ values.fetch key do
7
+ lookup( key, *default )
8
+ end
9
+ end
10
+
11
+ def set_constraints(**constraints)
12
+ @constraints << constraints
13
+ self
14
+ end
15
+
16
+ def set_defaults(**defaults)
17
+ invalidate_cache_and_errors
18
+ @defaults = defaults
19
+ self
20
+ end
21
+
22
+ def set_values a_hashy={}
23
+ invalidate_cache_and_errors
24
+
25
+ @values = a_hashy.dup rescue a_hashy
26
+ validate_constraints
27
+ self
28
+ end
29
+
30
+ def valid?; errors.empty? end
31
+
32
+ private
33
+ def evaluate val_or_proc
34
+ return evaluate_proc val_or_proc if Proc===val_or_proc
35
+ val_or_proc
36
+ end
37
+
38
+ def evaluate_proc a_proc
39
+ a_proc.arity == 1 ? instance_eval( &a_proc ) : instance_exec( &a_proc )
40
+ end
41
+
42
+ def initialize(**defaults)
43
+ set_defaults(**defaults)
44
+
45
+ @cache = {}
46
+ @values = {}
47
+
48
+ @constraints = []
49
+ @errors = []
50
+ end
51
+
52
+ def invalidate_cache_and_errors
53
+ @cache = {}
54
+ @errors = []
55
+ end
56
+
57
+ # Precondition: key not in values and key not in cache
58
+ # This explains the default value provided priority, we reason:
59
+ # An explicit default value in a get shall override the predefined defaults
60
+ # **But** that means that later caching will change the behavior of get not
61
+ # my preferred programming style. This might change in the future. (E.g.
62
+ # default comes before cache lookup).
63
+ def lookup key, *default
64
+ return default.first unless default.empty?
65
+ cache.fetch key do
66
+ raise KeyError, "#{key} not found in values, defaults or logic" unless defaults.has_key? key
67
+ cache[ key ] = evaluate( defaults[key] )
68
+ end
69
+ end
70
+
71
+ def validate_constraints
72
+ constraints.each do | constraint |
73
+ constraint.each do | k, c |
74
+ v = get k
75
+ if c.arity == 1
76
+ c.(v) || errors << "value error for key #{k.inspect} and value #{v.inspect}"
77
+ else
78
+ begin
79
+ instance_exec(&c) || errors << "value error for key #{k.inspect} and value #{v.inspect}"
80
+ rescue StandardError => e
81
+ errors << "constraint for key #{k.inspect} raised an error #{e}"
82
+ raise
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end # class IHash
89
+ end # module Lab42
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lab42_ihash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.beta
5
+ platform: ruby
6
+ authors:
7
+ - Robert Dober
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-nav
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ae
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: qed
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '2.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '2.9'
97
+ description: A Hash with Business Logic (call it intelligent).
98
+ email:
99
+ - robert.dober@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE
109
+ - README.md
110
+ - demo/000-introduction.md
111
+ - demo/050-constraints.md
112
+ - demo/080-business-logic.md
113
+ - demo/100-caching.md
114
+ - demo/applique/require_ae.rb
115
+ - demo/applique/require_ihash.rb
116
+ - lab42_ihash.gemspec
117
+ - lib/lab42/ihash.rb
118
+ - lib/lab42/ihash/version.rb
119
+ homepage: https://github.com/RobertDober/lab42_ihash
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: 2.0.0
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - '>='
135
+ - !ruby/object:Gem::Version
136
+ version: 2.2.2
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.2.2
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: 'A view over Hash like objects (needs to implement #fetch only). Allowing
143
+ to specify defaults, constraints and business logic. Implements caching for computed
144
+ values.'
145
+ test_files:
146
+ - demo/000-introduction.md
147
+ - demo/050-constraints.md
148
+ - demo/080-business-logic.md
149
+ - demo/100-caching.md
150
+ - demo/applique/require_ae.rb
151
+ - demo/applique/require_ihash.rb