bogo 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b544e3d18be2de80a851293f139ef363d3e2460
4
- data.tar.gz: 2634b067067e337a84006f5583263cbb18399930
3
+ metadata.gz: 03ed553a2ed1b83be48e18aeb962196071a2bb5d
4
+ data.tar.gz: b1466ec5ade9a0317e57a4e9999d1f8448051bd4
5
5
  SHA512:
6
- metadata.gz: 7c2f47cfac15a3cbcb72bd8e4d74dc2e2954512f7c8b4afff66624133eb5dfc93afaf2c16db37278cb38e4ff375fd632c8f2ec63fba83403f924f17139133f4d
7
- data.tar.gz: d5df748c23547d30bf5db35672c94bb489cfabbaf35125870a451e3c5dc6eb4e038358e7831deb0a7623d3706884e9ea312329acb281be7393bf36f86cf23bba
6
+ metadata.gz: 230d6b4ca8471a43489d7abe9f1bc883c6a71f20ca1b451103b54b72e1e881fba012a6b2239468c0b6a1005e155aabae0d98886f8d2187a199c9e9cde0bb4774
7
+ data.tar.gz: 850f441d6b9e1a42f066149dbd06cd70208b3405f040a4f30939e22d9c6e54bdb284bb68f0ad8039733372310a19e364773fbf082aa993652defbc2573e9da22
data/CHANGELOG.md CHANGED
@@ -1,2 +1,8 @@
1
+ ## v0.1.2
2
+ * Add initial spec coverage
3
+ * Always load `Bogo::Smash`
4
+ * Add support for global memoization
5
+ * Auto default lazy data on init
6
+
1
7
  ## v0.1.0
2
8
  * Initial release
data/README.md CHANGED
@@ -1,6 +1,213 @@
1
1
  # Bogo
2
2
 
3
- A collection of libraries.
3
+ A collection of helper libraries. What's in the box:
4
+
5
+ ## Animal strings
6
+
7
+ Convert camel cased strings to snake case or snake cased strings
8
+ to camel case:
9
+
10
+ ```ruby
11
+ require 'bogo'
12
+
13
+ class Stringer
14
+ include Bogo::AnimalStrings
15
+ end
16
+
17
+ str = Stringer.new
18
+ puts str.snake('CamelCasedString')
19
+ puts str.camel('snake_cased_string')
20
+ ```
21
+
22
+ ## Smash
23
+
24
+ Extension of the Hash class. It makes use of the `hashie` library and
25
+ adds a few extra features as well:
26
+
27
+ Included hashie modules:
28
+
29
+ * Hashie::Extensions::IndifferentAccess
30
+ * Hashie::Extensions::MergeInitializer
31
+ * Hashie::Extensions::DeepMerge
32
+ * Hashie::Extensions::Coercion
33
+
34
+ Added extras:
35
+
36
+ ### Conversion
37
+
38
+ Will convert from `Hash` to `Smash`. This conversion includes `Hash`
39
+ types found within `Array`s:
40
+
41
+ ```ruby
42
+ require 'bogo'
43
+
44
+ inst = {:a => 1, 'b' => 2, :c => [{:z => true}]}.to_smash
45
+ puts inst[:a]
46
+ puts inst['c'].first['z']
47
+ ```
48
+
49
+ and we can convert from `Smash` to `Hash` as well:
50
+
51
+ ```ruby
52
+ require 'bogo'
53
+
54
+ inst = {:a => 1, 'b' => 2, :c => [{:z => true}]}.to_smash
55
+ puts inst.class
56
+ puts inst[:c].first.class
57
+ inst = inst.to_hash
58
+ puts inst.class
59
+ puts inst['c'].first.class
60
+ ```
61
+
62
+ ### Path Walking
63
+
64
+ Values can be returned if given a path. If the path does not exist
65
+ a `nil` will be return instead of raising an exception:
66
+
67
+ ```ruby
68
+ require 'bogo'
69
+
70
+ inst = Smash.new(:a => {:b => {:c => {:d => 1}}})
71
+ puts inst.get(:a, :b, :c, :d)
72
+ puts inst.get(:a, :c, :x, :z)
73
+ ```
74
+
75
+ ### Default value on missing path
76
+
77
+ Use `#fetch` to provide default value if path does not exist. The
78
+ last value in the list will be used as the returned value:
79
+
80
+ ```ruby
81
+ require 'bogo'
82
+
83
+ inst = Smash.new(:a => 1)
84
+ puts inst.fetch(:b, :c, 2)
85
+ ```
86
+
87
+ ### Set value at path
88
+
89
+ Set deeply nested values by providing the path. The last value
90
+ in the list will be set:
91
+
92
+ ```ruby
93
+ require 'bogo'
94
+
95
+ inst = Smash.new
96
+ inst.set(:a, :b, :c, :d, :e, 1)
97
+ puts inst.get(:a, :b, :c, :d, :e)
98
+ ```
99
+
100
+ ### Checksums
101
+
102
+ Checksum will generate a new `Smash` instance with sorted keys
103
+ and then generate a SHA256 digest:
104
+
105
+ ```ruby
106
+ require 'bogo'
107
+
108
+ puts Smash.new(:a => 1, :b => 2, :c => 3).checksum
109
+ puts Smash.new(:c => 3, :b => 2, :a => 1).checksum
110
+ ```
111
+
112
+ ## Memoization
113
+
114
+ Memoization helpers for thread and object local, thread local,
115
+ and global memoization:
116
+
117
+ ```ruby
118
+ require 'bogo'
119
+
120
+ class Memo
121
+ include Bogo::Memoization
122
+
123
+ def object_value(provided_value)
124
+ memoize(:value){ provided_value }
125
+ end
126
+
127
+ def thread_value(provided_value)
128
+ memoize(:value, true){ provided_value }
129
+ end
130
+
131
+ def global_value(provided_value)
132
+ memoize(:value, :global){ provided_value }
133
+ end
134
+ end
135
+
136
+ obj1 = Memo.new
137
+ obj2 = Memo.new
138
+
139
+ obj1.object_value('ohai')
140
+ obj1.thread_value('obai')
141
+ obj1.global_value('ohey')
142
+
143
+ puts '--- obj1 start'
144
+ puts obj1.object_value('fubar')
145
+ puts obj1.thread_value('fubar')
146
+ puts obj1.global_value('fubar')
147
+ puts '--- obj1 end'
148
+ puts '--- obj2 start'
149
+ puts obj2.object_value('fubar')
150
+ puts obj2.thread_value('fubar')
151
+ puts obj2.global_value('fubar')
152
+ puts '--- obj2 end'
153
+
154
+ ## Lazy
155
+
156
+ Easily define attributes within a class. Provides
157
+ type checking, coercion, and callback integration
158
+ for dependencies and missing values.
159
+
160
+ ```ruby
161
+ require 'bogo'
162
+
163
+ class MyData
164
+ include Bogo::Lazy
165
+
166
+ attribute :name, String, :default => 'MyData'
167
+ attribute :data_id, [String, Numeric]
168
+ attribute :count, Float, :coerce => lambda{|v| v.to_f}
169
+ attribute :remote_id, Integer, :depends => :remote_loader
170
+ attribute :stuff, String
171
+
172
+ on_missing :load_things
173
+
174
+ def remote_loader
175
+ data[:remote_id] = 42
176
+ end
177
+
178
+ def load_things
179
+ data[:stuff] = 'ALL THE THINGS'
180
+ end
181
+ end
182
+
183
+ data = MyData.new
184
+
185
+ puts data.name
186
+ data.name = 'New name!'
187
+ puts data.name
188
+ data.data_id = 1
189
+ puts data.data_id
190
+ data.data_id = 'one'
191
+ puts data.data_id
192
+ begin
193
+ data.data_id = :one
194
+ rescue TypeError => e
195
+ puts "#{e.class}: #{e}"
196
+ end
197
+ data.count = '1'
198
+ p data.count
199
+ puts data.remote_id
200
+ puts data.stuff
201
+ p data.dirty?(:name)
202
+ p data.data_id
203
+ p data.data
204
+ p data.dirty
205
+ p data.attributes
206
+ p data.dirty?
207
+ data.valid_state
208
+ p data.dirty?
209
+ p data.data
210
+ ```
4
211
 
5
212
  ## Info
6
213
  * Repository: https://github.com/spox/bogo
data/bogo.gemspec CHANGED
@@ -11,5 +11,6 @@ Gem::Specification.new do |s|
11
11
  s.require_path = 'lib'
12
12
  s.license = 'Apache 2.0'
13
13
  s.add_dependency 'hashie'
14
+ s.add_dependency 'multi_json'
14
15
  s.files = Dir['lib/**/*'] + %w(bogo.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
15
16
  end
data/lib/bogo.rb CHANGED
@@ -7,4 +7,5 @@ module Bogo
7
7
  autoload :Smash, 'bogo/smash'
8
8
  end
9
9
 
10
- autoload :Smash, 'bogo/smash'
10
+ # Always load smash
11
+ require 'bogo/smash'
data/lib/bogo/lazy.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bogo'
2
+ require 'multi_json'
2
3
  require 'digest/sha2'
3
4
 
4
5
  module Bogo
@@ -12,6 +13,11 @@ module Bogo
12
13
  def data
13
14
  unless(@data)
14
15
  @data = Smash.new
16
+ self.class.attributes.each do |key, value|
17
+ if(value.has_key?('default'))
18
+ @data[key] = value['default']
19
+ end
20
+ end
15
21
  end
16
22
  @data
17
23
  end
@@ -4,6 +4,38 @@ module Bogo
4
4
  # Memoization helpers
5
5
  module Memoization
6
6
 
7
+ class << self
8
+
9
+ # Clean up isolated memoizations
10
+ #
11
+ # @param object_id [Object]
12
+ # @return [Proc]
13
+ def cleanup(object_id)
14
+ proc do
15
+ Thread.current[:bogo_memoization].delete_if do |k,v|
16
+ k.to_s.start_with?(object_id.to_s)
17
+ end
18
+ end
19
+ end
20
+
21
+ # Clear thread memoizations
22
+ #
23
+ # @return [nil]
24
+ def clear_current!
25
+ Thread.current[:bogo_memoization] = nil
26
+ end
27
+
28
+ # Clear global memoizations
29
+ #
30
+ # @return [nil]
31
+ def clear_global!
32
+ Thread.exclusive do
33
+ $bogo_memoization = Smash.new
34
+ end
35
+ end
36
+
37
+ end
38
+
7
39
  # Memoize data
8
40
  #
9
41
  # @param key [String, Symbol] identifier for data
@@ -15,14 +47,29 @@ module Bogo
15
47
  unless(direct)
16
48
  key = "#{self.object_id}_#{key}"
17
49
  end
18
- unless(_memo.has_key?(key))
19
- _memo[key] = yield
50
+ if(direct == :global)
51
+ Thread.exclusive do
52
+ $bogo_memoization ||= Smash.new
53
+ unless($bogo_memoization.has_key?(key))
54
+ $bogo_memoization[key] = yield
55
+ end
56
+ $bogo_memoization[key]
57
+ end
58
+ else
59
+ unless(_memo.has_key?(key))
60
+ _memo[key] = yield
61
+ end
62
+ _memo[key]
20
63
  end
21
- _memo[key]
22
64
  end
23
65
 
66
+ # @return [Smash] memoization hash for current thread
24
67
  def _memo
25
- Thread.current[:bogo_memoization] ||= Smash.new
68
+ unless(Thread.current[:bogo_memoization])
69
+ Thread.current[:bogo_memoization] = Smash.new
70
+ ObjectSpace.define_finalizer(self, Bogo::Memoization.cleanup(self.object_id))
71
+ end
72
+ Thread.current[:bogo_memoization]
26
73
  end
27
74
 
28
75
  # Remove memoized value
@@ -34,7 +81,14 @@ module Bogo
34
81
  unless(direct)
35
82
  key = "#{self.object_id}_#{key}"
36
83
  end
37
- _memo.delete(key)
84
+ if(direct == :global)
85
+ Thread.exclusive do
86
+ $bogo_memoization ||= Smash.new
87
+ $bogo_memoization.delete(key)
88
+ end
89
+ else
90
+ _memo.delete(key)
91
+ end
38
92
  end
39
93
 
40
94
  # Remove all memoized values
data/lib/bogo/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Bogo
2
2
  # Current library version
3
- VERSION = Gem::Version.new('0.1.0')
3
+ VERSION = Gem::Version.new('0.1.2')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bogo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-29 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: Helper libraries
28
42
  email: code@chrisroberts.org
29
43
  executables: []