bogo 0.1.0 → 0.1.2

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.
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: []