ribbon 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,8 @@
1
1
  %w(
2
2
 
3
- ribbon/core_extensions/basic_object
4
3
  ribbon/gem
5
4
  ribbon/options
6
- ribbon/wrapper
5
+ ribbon/raw
7
6
 
8
7
  ).each { |file| require file }
9
8
 
@@ -56,142 +55,127 @@ ribbon/wrapper
56
55
  #
57
56
  # @author Matheus Afonso Martins Moreira
58
57
  # @since 0.1.0
59
- # @see Ribbon::Wrapper
60
- class Ribbon < BasicObject
58
+ # @see Ribbon::Raw
59
+ class Ribbon
61
60
 
62
- # The hash used internally.
61
+ # The raw ribbon.
63
62
  #
64
- # @return [Hash] the hash used by this Ribbon instance to store data
65
- # @api private
66
- def __hash__
67
- @hash ||= (::Hash.new &::Ribbon.default_value_proc)
63
+ # @return [Ribbon::Raw] this ribbon's raw ribbon
64
+ # @since 0.8.0
65
+ def raw
66
+ @raw ||= Ribbon::Raw.new
68
67
  end
69
68
 
70
- # Initializes a new ribbon.
69
+ # Sets this ribbon's raw ribbon.
70
+ #
71
+ # @param [Ribbon, Ribbon::Raw, #to_hash] object the hash-like object
72
+ # @return [Ribbon::Raw] the raw ribbon
73
+ # @since 0.8.0
74
+ def raw=(object)
75
+ @raw = Ribbon.extract_raw_from object
76
+ end
77
+
78
+ # Initializes a new ribbon with the given values.
71
79
  #
72
80
  # If given a block, the ribbon will be yielded to it. If the block doesn't
73
81
  # take any arguments, it will be evaluated in the context of the ribbon.
74
82
  #
75
- # All objects inside the hash will be converted.
76
- #
77
- # @param [#to_hash, Ribbon, Ribbon::Wrapper] hash the hash with the initial
78
- # values
79
- # @see CoreExt::BasicObject#__yield_or_eval__
80
- # @see convert_all!
81
- def initialize(hash = {}, &block)
82
- __hash__.merge! ::Ribbon.extract_hash_from(hash)
83
+ # @param [Ribbon, Ribbon::Raw, #to_hash] initial_values the initial values
84
+ # @see #raw=
85
+ # @see Ribbon::Raw#initialize
86
+ def initialize(initial_values = Ribbon::Raw.new, &block)
87
+ self.raw = initial_values
83
88
  __yield_or_eval__ &block
84
- ::Ribbon.convert_all! self
85
89
  end
86
90
 
87
- # Fetches the value associated with the given key.
88
- #
89
- # If given a block, the value will be yielded to it. If the block doesn't take
90
- # any arguments, it will be evaluated in the context of the value.
91
+ # The hash used by the raw ribbon.
91
92
  #
92
- # @param key the key which identifies the value
93
- # @return the value associated with the given key
94
- # @see CoreExt::BasicObject#__yield_or_eval__
95
- def [](key, &block)
96
- value = ::Ribbon.convert __hash__[key]
97
- value.__yield_or_eval__ &block
98
- self[key] = value
93
+ # @return [Hash] the internal hash of the raw ribbon
94
+ # @since 0.8.0
95
+ def internal_hash
96
+ raw.__hash__
99
97
  end
100
98
 
101
- # Associates the given values with the given key.
102
- #
103
- # @param key the key that will identify the values
104
- # @param values the values that will be associated with the key
105
- # @example
106
- # ribbon = Ribbon.new
107
- #
108
- # ribbon[:key] = :value
109
- # ribbon[:key]
110
- # # => :value
111
- #
112
- # ribbon[:key] = :multiple, :values
113
- # ribbon[:key]
114
- # # => [:multiple, :values]
115
- def []=(key, *values)
116
- __hash__[key] = if values.size == 1 then values.first else values end
99
+ # Forwards the method, arguments and block to the raw ribbon's hash, if it
100
+ # responds to the method, or to the raw ribbon itself otherwise.
101
+ def method_missing(method, *arguments, &block)
102
+ if (hash = internal_hash).respond_to? method then hash
103
+ else raw end.__send__ method, *arguments, &block
117
104
  end
118
105
 
119
- # Handles the following cases:
106
+ # Merges everything inside this ribbon with everything inside the given
107
+ # ribbon, creating a new instance in the process.
120
108
  #
121
- # ribbon.method => ribbon[method]
122
- # ribbon.method value => ribbon[method] = value
123
- # ribbon.method &block => ribbon[method, &block]
124
- # ribbon.method value, &block => ribbon[method] = value
125
- # ribbon[method, &block]
109
+ # @param [Ribbon, Ribbon::Raw, #to_hash] ribbon the ribbon with new values
110
+ # @return [Ribbon] a new ribbon containing the results of the deep merge
111
+ # @yieldparam key the key which identifies both values
112
+ # @yieldparam old_value the value from this ribbon
113
+ # @yieldparam new_value the value from the given ribbon
114
+ # @yieldreturn the object that will be used as the new value
115
+ # @since 0.8.0
116
+ # @see #deep_merge!
117
+ # @see deep_merge
118
+ def deep_merge(ribbon, &block)
119
+ Ribbon.new Ribbon.deep_merge(self, ribbon, &block)
120
+ end
121
+
122
+ # Merges everything inside this ribbon with the given ribbon in place.
126
123
  #
127
- # ribbon.method = value => ribbon[method] = value
124
+ # @param [Ribbon, Ribbon::Raw, #to_hash] ribbon the ribbon with new values
125
+ # @return [self] this ribbon
126
+ # @yieldparam key the key which identifies both values
127
+ # @yieldparam old_value the value from this ribbon
128
+ # @yieldparam new_value the value from the given ribbon
129
+ # @yieldreturn the object that will be used as the new value
130
+ # @since 0.8.0
131
+ # @see #deep_merge
132
+ # @see deep_merge!
133
+ def deep_merge!(ribbon, &block)
134
+ Ribbon.deep_merge! self, ribbon, &block
135
+ end
136
+
137
+ # Converts this ribbon and all ribbons inside into hashes.
128
138
  #
129
- # ribbon.method! value => ribbon[method] = value
130
- # self
131
- # ribbon.method! &block => ribbon[method, &block]
132
- # self
133
- # ribbon.method! value, &block => ribbon[method] = value
134
- # ribbon[method, &block]
135
- # self
139
+ # @return [Hash] the converted contents of this wrapped ribbon
140
+ # @since 0.8.0
141
+ def to_hash
142
+ to_hash_recursive
143
+ end
144
+
145
+ # Converts this ribbon to a hash and serializes it with YAML.
136
146
  #
137
- # ribbon.method? => ribbon.__hash__.fetch method
138
- # ribbon.method? value => ribbon.__hash__.fetch method, value
139
- # ribbon.method? &block => ribbon.__hash__.fetch method, &block
140
- # ribbon.method? value, &block => ribbon.__hash__.fetch method, value, &block
141
- def method_missing(method, *args, &block)
142
- method_string = method.to_s
143
- key = method_string.strip.gsub(/[=?!]$/, '').strip.intern
144
- case method_string[-1]
145
- when ?=
146
- __send__ :[]=, key, *args
147
- when ?!
148
- __send__ :[]=, key, *args unless args.empty?
149
- self[key, &block]
150
- self
151
- when ??
152
- begin self.__hash__.fetch key, *args, &block
153
- rescue ::KeyError; nil end
154
- else
155
- __send__ :[]=, key, *args unless args.empty?
156
- self[key, &block]
157
- end
147
+ # @return [String] the YAML string that represents this ribbon
148
+ # @since 0.8.0
149
+ # @see from_yaml
150
+ def to_yaml
151
+ to_hash.to_yaml
158
152
  end
159
153
 
160
- # Generates a simple <tt>key: value</tt> string representation of this ribbon.
154
+ # Delegates to the raw ribbon.
161
155
  #
162
- # @option opts [String] :separator Separates the key/value pair.
163
- # Default is <tt>': '</tt>.
164
- # @option opts [Symbol] :key Will be sent to the key in order to convert
165
- # it to a string. Default is <tt>:to_s</tt>.
166
- # @option opts [Symbol] :value Will be sent to the value in order to
167
- # convert it to a string. Default is
168
- # <tt>:inspect</tt>.
169
156
  # @return [String] the string representation of this ribbon
170
- def to_s(opts = {})
171
- __to_s_recursive__ ::Ribbon.extract_hash_from(opts)
157
+ # @see Ribbon::Raw#to_s
158
+ def to_s(*arguments, &block)
159
+ raw.to_s *arguments, &block
172
160
  end
173
161
 
174
162
  alias inspect to_s
175
163
 
176
164
  private
177
165
 
178
- # Computes a string value recursively for the given ribbon, and all ribbons
179
- # inside it, using the given options.
166
+ # Converts this ribbon and all ribbons inside into hashes using recursion.
180
167
  #
181
- # @since 0.3.0
182
- # @see #to_s
183
- def __to_s_recursive__(opts = {}, ribbon = self)
184
- ksym = opts.fetch(:key, :to_s).to_sym
185
- vsym = opts.fetch(:value, :inspect).to_sym
186
- separator = opts.fetch(:separator, ': ').to_s
187
- values = ribbon.__hash__.map do |k, v|
188
- k = k.ribbon if ::Ribbon.wrapped? k
189
- v = v.ribbon if ::Ribbon.wrapped? v
190
- k = if ::Ribbon.instance? k then __to_s_recursive__ opts, k else k.__send__ ksym end
191
- v = if ::Ribbon.instance? v then __to_s_recursive__ opts, v else v.__send__ vsym end
192
- "#{k}#{separator}#{v}"
193
- end.join ', '
194
- "{#{values}}"
168
+ # @return [Hash] the converted contents of this ribbon
169
+ def to_hash_recursive(raw_ribbon = self.raw)
170
+ {}.tap do |hash|
171
+ raw_ribbon.__hash__.each do |key, value|
172
+ hash[key] = case value
173
+ when Ribbon then to_hash_recursive value.raw
174
+ when Ribbon::Raw then to_hash_recursive value
175
+ else value
176
+ end
177
+ end
178
+ end
195
179
  end
196
180
 
197
181
  end
@@ -200,57 +184,70 @@ class << Ribbon
200
184
 
201
185
  alias [] new
202
186
 
203
- # Proc used to store a new Ribbon instance as the value of a missing key.
187
+ # Whether the given object is a {Ribbon::Raw raw ribbon}.
204
188
  #
205
- # @return [Proc] the proc used when constructing new hashes
206
- # @since 0.4.6
207
- def default_value_proc
208
- @default_value_proc ||= (proc { |hash, key| hash[key] = Ribbon.new })
189
+ # @param object the object to be tested
190
+ # @return [true, false] whether the object is a raw ribbon
191
+ # @since 0.8.0
192
+ def raw?(object)
193
+ Ribbon::Raw === object
209
194
  end
210
195
 
211
- # Converts hashes to ribbons. Will look inside arrays.
196
+ # Whether the object is compatible with methods that take hashes or ribbons as
197
+ # arguments.
212
198
  #
213
- # @param object the object to convert
214
- # @return the converted value
215
- # @since 0.2.0
216
- def convert(object)
199
+ # @param object the object to be tested
200
+ # @return [true, false] whether the object is a raw ribbon
201
+ # @since 0.8.0
202
+ def compatible?(object)
203
+ [Ribbon, Ribbon::Raw, Hash].any? { |type| type === object }
204
+ end
205
+
206
+ # Extracts the hash of a ribbon. Will attempt to convert other objects.
207
+ #
208
+ # @param [Ribbon, Ribbon::Raw, #to_hash] object the object to convert
209
+ # @return [Hash] the resulting hash
210
+ # @since 0.2.1
211
+ def extract_hash_from(object)
217
212
  case object
218
- when Hash then Ribbon.new object
219
- when Array then object.map { |element| convert element }
220
- else object
213
+ when Ribbon, Ribbon::Raw then object.__hash__
214
+ else object.to_hash
221
215
  end
222
216
  end
223
217
 
224
- # Converts all values inside the given ribbon.
218
+ # Extracts a raw ribbon from the given object.
225
219
  #
226
- # @param [Ribbon, Ribbon::Wrapper] ribbon the ribbon whose values are to be
227
- # converted
228
- # @return [Ribbon, Ribbon::Wrapper] the ribbon with all values converted
229
- # @since 0.2.0
230
- # @see convert
231
- def convert_all!(ribbon)
232
- ribbon.__hash__.each do |key, value|
233
- ribbon[key] = case value
234
- when Ribbon then convert_all! value
235
- when Ribbon::Wrapper then convert_all! value.ribbon
236
- else convert value
237
- end
220
+ # @param [Ribbon, Ribbon::Raw, #to_hash] object the hash-like object
221
+ # @return [Ribbon::Raw] the raw ribbon
222
+ # @since 0.8.0
223
+ def extract_raw_from(object)
224
+ case object
225
+ when Ribbon then object.raw
226
+ when Ribbon::Raw then object
227
+ else Ribbon::Raw.new object.to_hash
238
228
  end
239
- ribbon
229
+ end
230
+
231
+ # Deserializes the hash from the string using YAML and uses it to construct a
232
+ # new ribbon.
233
+ #
234
+ # @param [String] string a valid YAML string
235
+ # @return [Ribbon] a new Ribbon
236
+ # @since 0.4.7
237
+ def from_yaml(string)
238
+ Ribbon.new YAML.load(string)
240
239
  end
241
240
 
242
241
  # Merges the hashes of the given ribbons.
243
242
  #
244
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] old_ribbon the ribbon with old
245
- # values
246
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] new_ribbon the ribbon with new
247
- # values
243
+ # @param [Ribbon, Ribbon::Raw, #to_hash] old_ribbon the ribbon with old values
244
+ # @param [Ribbon, Ribbon::Raw, #to_hash] new_ribbon the ribbon with new values
248
245
  # @return [Ribbon] a new ribbon containing the results of the merge
249
246
  # @yieldparam key the key which identifies both values
250
247
  # @yieldparam old_value the value from old_ribbon
251
248
  # @yieldparam new_value the value from new_ribbon
252
249
  # @yieldreturn the object that will be used as the new value
253
- # @since 0.3.0
250
+ # @since 0.8.0
254
251
  # @see merge!
255
252
  # @see extract_hash_from
256
253
  def merge(old_ribbon, new_ribbon, &block)
@@ -262,17 +259,15 @@ class << Ribbon
262
259
 
263
260
  # Merges the hashes of the given ribbons in place.
264
261
  #
265
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] old_ribbon the ribbon with old
266
- # values
267
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] new_ribbon the ribbon with new
268
- # values
269
- # @return [Ribbon, Ribbon::Wrapper, Hash] old_ribbon, which will contain the
270
- # results of the merge
262
+ # @param [Ribbon, Ribbon::Raw, #to_hash] old_ribbon the ribbon with old values
263
+ # @param [Ribbon, Ribbon::Raw, #to_hash] new_ribbon the ribbon with new values
264
+ # @return [Ribbon, Ribbon::Raw, Hash] old_ribbon, which will contain the
265
+ # results of the merge
271
266
  # @yieldparam key the key which identifies both values
272
267
  # @yieldparam old_value the value from old_ribbon
273
268
  # @yieldparam new_value the value from new_ribbon
274
269
  # @yieldreturn the object that will be used as the new value
275
- # @since 0.3.0
270
+ # @since 0.8.0
276
271
  # @see merge
277
272
  # @see extract_hash_from
278
273
  def merge!(old_ribbon, new_ribbon, &block)
@@ -284,16 +279,14 @@ class << Ribbon
284
279
 
285
280
  # Merges everything inside the given ribbons.
286
281
  #
287
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] old_ribbon the ribbon with old
288
- # values
289
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] new_ribbon the ribbon with new
290
- # values
282
+ # @param [Ribbon, Ribbon::Raw, #to_hash] old_ribbon the ribbon with old values
283
+ # @param [Ribbon, Ribbon::Raw, #to_hash] new_ribbon the ribbon with new values
291
284
  # @return [Ribbon] a new ribbon containing the results of the merge
292
285
  # @yieldparam key the key which identifies both values
293
286
  # @yieldparam old_value the value from old_ribbon
294
287
  # @yieldparam new_value the value from new_ribbon
295
288
  # @yieldreturn the object that will be used as the new value
296
- # @since 0.4.5
289
+ # @since 0.8.0
297
290
  # @see merge
298
291
  # @see deep_merge!
299
292
  # @see extract_hash_from
@@ -303,17 +296,15 @@ class << Ribbon
303
296
 
304
297
  # Merges everything inside the given ribbons in place.
305
298
  #
306
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] old_ribbon the ribbon with old
307
- # values
308
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] new_ribbon the ribbon with new
309
- # values
310
- # @return [Ribbon, Ribbon::Wrapper, Hash] old_ribbon, which will contain the
311
- # results of the merge
299
+ # @param [Ribbon, Ribbon::Raw, #to_hash] old_ribbon the ribbon with old values
300
+ # @param [Ribbon, Ribbon::Raw, #to_hash] new_ribbon the ribbon with new values
301
+ # @return [Ribbon, Ribbon::Raw, Hash] old_ribbon, which will contain the
302
+ # results of the merge
312
303
  # @yieldparam key the key which identifies both values
313
304
  # @yieldparam old_value the value from old_ribbon
314
305
  # @yieldparam new_value the value from new_ribbon
315
306
  # @yieldreturn the object that will be used as the new value
316
- # @since 0.4.5
307
+ # @since 0.8.0
317
308
  # @see merge!
318
309
  # @see deep_merge
319
310
  # @see extract_hash_from
@@ -321,74 +312,26 @@ class << Ribbon
321
312
  deep :merge!, old_ribbon, new_ribbon, &block
322
313
  end
323
314
 
324
- # Tests whether the given object is an instance of Ribbon.
325
- #
326
- # @param object the object to be tested
327
- # @return [true, false] whether the object is an instance of Ribbon
328
- # @since 0.2.0
329
- def instance?(object)
330
- Ribbon === object
331
- end
332
-
333
- # Tests whether the given object is an instance of {Ribbon::Wrapper}.
334
- #
335
- # @param object the object to be tested
336
- # @return [true, false] whether the object is an instance of {Ribbon::Wrapper}
337
- # @since 0.2.0
338
- def wrapped?(ribbon)
339
- Ribbon::Wrapper === ribbon
340
- end
341
-
342
- # Wraps an object in a {Ribbon::Wrapper}.
343
- #
344
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] object the object to be wrapped
345
- # @return [Ribbon::Wrapper] a new wrapped ribbon
346
- # @since 0.2.0
347
- def wrap(object = ::Ribbon.new, &block)
348
- Ribbon::Wrapper.new object, &block
349
- end
350
-
351
- # Returns the hash of a Ribbon. Will attempt to convert other objects.
352
- #
353
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] parameter the object to convert
354
- # @return [Hash] the resulting hash
355
- # @since 0.2.1
356
- def extract_hash_from(parameter)
357
- case parameter
358
- when Ribbon::Wrapper then parameter.internal_hash
359
- when Ribbon then parameter.__hash__
360
- else parameter.to_hash
361
- end
362
- end
363
-
364
- # Deserializes the hash from the string using YAML and uses it to construct a
365
- # new ribbon.
366
- #
367
- # @param [String] string a valid YAML string
368
- # @return [Ribbon] a new Ribbon
369
- # @since 0.4.7
370
- def from_yaml(string)
371
- Ribbon.new YAML.load(string)
372
- end
373
-
374
315
  private
375
316
 
376
- # Common logic for deep merge methods. +merge_method+ should be either
377
- # +:merge+ or +:merge!+, and denotes which method will be used to merge
378
- # recursively.
317
+ # Common logic for deep merge methods.
379
318
  #
319
+ # @param [:merge, :merge!] merge_method the method that will be used to merge
320
+ # recursively
321
+ # @param [Ribbon, Ribbon::Raw, #to_hash] old_ribbon the ribbon with old values
322
+ # @param [Ribbon, Ribbon::Raw, #to_hash] new_ribbon the ribbon with new values
380
323
  # @yieldparam key the key which identifies both values
381
324
  # @yieldparam old_value the value from old_ribbon
382
325
  # @yieldparam new_value the value from new_ribbon
383
326
  # @yieldreturn the object that will be used as the new value
384
- # @since 0.4.5
327
+ # @since 0.8.0
385
328
  # @see merge!
386
329
  # @see merge
387
330
  # @see deep_merge
388
331
  # @see deep_merge!
389
332
  def deep(merge_method, old_ribbon, new_ribbon, &block)
390
333
  send merge_method, old_ribbon, new_ribbon do |key, old_value, new_value|
391
- if instance?(old_value) and instance?(new_value)
334
+ if [old_value, new_value].all? { |value| compatible? value }
392
335
  deep merge_method, old_value, new_value, &block
393
336
  else
394
337
  if block then block.call key, old_value, new_value
@@ -1,4 +1,4 @@
1
- class Ribbon < BasicObject
1
+ class Ribbon
2
2
 
3
3
  # Extensions to the standard library.
4
4
  #
@@ -8,6 +8,11 @@ class Ribbon < BasicObject
8
8
 
9
9
  end
10
10
 
11
- %w(array basic_object hash object).each do |file|
12
- require file.prepend 'ribbon/core_extensions/'
13
- end
11
+ %w(
12
+
13
+ ribbon/core_extensions/array
14
+ ribbon/core_extensions/basic_object
15
+ ribbon/core_extensions/hash
16
+ ribbon/core_extensions/object
17
+
18
+ ).each { |file| require file }
@@ -1,6 +1,6 @@
1
1
  require 'ribbon'
2
2
 
3
- class Ribbon < BasicObject
3
+ class Ribbon
4
4
  module CoreExtensions
5
5
 
6
6
  # Methods to work with ribbons in arrays.
@@ -9,37 +9,30 @@ class Ribbon < BasicObject
9
9
  # @since 0.6.0
10
10
  module Array
11
11
 
12
- # If the last argument is a hash, removes and converts it to a ribbon,
13
- # otherwise returns an empty ribbon.
12
+ # Extracts the last argument as a ribbon or returns an empty one.
14
13
  #
15
- # @return [Ribbon] the Ribbon at the end of this array
14
+ # @return [Ribbon] the ribbon at the end of this array
15
+ # @see #extract_raw_ribbon
16
16
  def extract_ribbon!
17
17
  case last
18
- when Hash then Ribbon.new pop
18
+ when Hash, Ribbon::Raw then Ribbon.new pop
19
19
  when Ribbon then pop
20
- when Ribbon::Wrapper then pop.ribbon
21
20
  else Ribbon.new
22
21
  end
23
22
  end
24
23
 
25
- # Extracts the last argument as a wrapped ribbon, or returns an empty one.
26
- # See #extract_ribbon! for details.
27
- #
28
- # @return [Ribbon::Wrapper] the wrapped Ribbon at the end of this array
29
- def extract_wrapped_ribbon!
30
- Ribbon.wrap extract_ribbon!
31
- end
32
-
33
- # Same as #extract_ribbon!
34
- #
35
- #
36
- # @return [Ribbon] the Ribbon at the end of this array
37
24
  alias extract_options_as_ribbon! extract_ribbon!
38
25
 
39
- # Same as #extract_wrapped_ribbon!
26
+ # Extracts the last argument as a raw ribbon or returns an empty one.
40
27
  #
41
- # @return [Ribbon::Wrapper] the wrapped Ribbon at the end of this array
42
- alias extract_options_as_wrapped_ribbon! extract_wrapped_ribbon!
28
+ # @return [Ribbon::Raw] the raw ribbon at the end of this array
29
+ # @since 0.8.0
30
+ # @see #extract_ribbon!
31
+ def extract_raw_ribbon!
32
+ Ribbon::Raw.new extract_ribbon!
33
+ end
34
+
35
+ alias extract_options_as_raw_ribbon! extract_raw_ribbon!
43
36
 
44
37
  end
45
38
 
@@ -1,4 +1,4 @@
1
- class Ribbon < BasicObject
1
+ class Ribbon
2
2
  module CoreExtensions
3
3
 
4
4
  # Some useful methods.
@@ -8,12 +8,16 @@ class Ribbon < BasicObject
8
8
  module BasicObject
9
9
 
10
10
  # Evaluates the block using +instance_eval+ if it takes no arguments;
11
- # yields +self+ to it otherwise.
11
+ # yields this object to it otherwise.
12
12
  #
13
- # @yieldparam [self] object this instance
14
- # @return [Object, nil] the result of the block or nil if not given one
13
+ # @yieldparam [self] object this object
14
+ # @return [::Object, nil] the result of the block or nil if not given one
15
15
  def __yield_or_eval__(&block)
16
- if block.arity.zero? then instance_eval &block else block.call self end if block
16
+ if block.arity.zero?
17
+ instance_eval &block
18
+ else
19
+ block.call self
20
+ end unless block.nil?
17
21
  end
18
22
 
19
23
  end
@@ -1,6 +1,6 @@
1
1
  require 'ribbon'
2
2
 
3
- class Ribbon < BasicObject
3
+ class Ribbon
4
4
  module CoreExtensions
5
5
 
6
6
  # Includes methods to convert hashes to ribbons.
@@ -9,29 +9,22 @@ class Ribbon < BasicObject
9
9
  # @since 0.6.0
10
10
  module Hash
11
11
 
12
- # Converts this hash to a Ribbon.
12
+ # Converts this hash to a ribbon.
13
13
  #
14
- # @return a new Ribbon with the contents of this hash
14
+ # @return [Ribbon] a new ribbon with the contents of this hash
15
15
  def to_ribbon
16
16
  Ribbon.new self
17
17
  end
18
18
 
19
- # Converts this hash to a Ribbon::Wrapper.
20
- #
21
- # @return a new wrapped Ribbon with the contents of this hash
22
- def to_ribbon_wrapper
23
- Ribbon.wrap self
24
- end
25
-
26
- # Same as #to_ribbon.
27
- #
28
- # @return a new Ribbon with the contents of this hash
29
19
  alias to_rbon to_ribbon
30
20
 
31
- # Same as #to_ribbon_wrapper.
21
+ # Converts this hash to a raw ribbon.
32
22
  #
33
- # @return a new wrapped Ribbon with the contents of this hash
34
- alias to_wrapped_ribbon to_ribbon_wrapper
23
+ # @return [Ribbon::Raw] a new raw ribbon with the contents of this hash
24
+ # @since 0.8.0
25
+ def to_raw_ribbon
26
+ Ribbon.wrap self
27
+ end
35
28
 
36
29
  end
37
30
 
@@ -1,4 +1,4 @@
1
- class Ribbon < BasicObject
1
+ class Ribbon
2
2
  module CoreExtensions
3
3
 
4
4
  # Methods available to all objects.
@@ -13,6 +13,9 @@ class Ribbon < BasicObject
13
13
  end
14
14
  end
15
15
 
16
- %w(option_scope yield_or_eval).each do |file|
17
- require file.prepend 'ribbon/core_extensions/object/'
18
- end
16
+ %w(
17
+
18
+ ribbon/core_extensions/object/option_scope
19
+ ribbon/core_extensions/object/yield_or_eval
20
+
21
+ ).each { |file| require file }
@@ -1,6 +1,6 @@
1
1
  require 'ribbon/options'
2
2
 
3
- class Ribbon < BasicObject
3
+ class Ribbon
4
4
  module CoreExtensions
5
5
 
6
6
  module Object
@@ -1,6 +1,6 @@
1
1
  require 'ribbon/core_extensions/basic_object'
2
2
 
3
- class Ribbon < BasicObject
3
+ class Ribbon
4
4
  module CoreExtensions
5
5
 
6
6
  module Object
@@ -1,6 +1,6 @@
1
1
  require 'jewel'
2
2
 
3
- class Ribbon < BasicObject
3
+ class Ribbon
4
4
 
5
5
  # Ribbon gem information and metadata.
6
6
  #
@@ -1,7 +1,11 @@
1
- require 'ribbon'
2
- require 'ribbon/core_extensions/array'
1
+ %w(
3
2
 
4
- class Ribbon < BasicObject
3
+ ribbon
4
+ ribbon/core_extensions/array
5
+
6
+ ).each { |file| require file }
7
+
8
+ class Ribbon
5
9
 
6
10
  # Applies options to all method calls.
7
11
  #
@@ -23,10 +27,9 @@ class Ribbon < BasicObject
23
27
  # the block immediately, if given one.
24
28
  #
25
29
  # @param receiver the object that will be receiving the methods
26
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] options the options that will
27
- # be applied to all
28
- # methods
29
- # @see CoreExt::BasicObject#__yield_or_eval__
30
+ # @param [Ribbon, Ribbon::Raw, #to_hash] options the options that will be
31
+ # applied to all methods
32
+ # @see CoreExtensions::BasicObject#__yield_or_eval__
30
33
  def initialize(receiver, options = {}, &block)
31
34
  @receiver, @options = receiver, options
32
35
  __yield_or_eval__ &block
@@ -0,0 +1,195 @@
1
+ %w(
2
+
3
+ ribbon
4
+ ribbon/core_extensions/basic_object
5
+
6
+ ).each { |file| require file }
7
+
8
+ class Ribbon
9
+
10
+ # Ribbon with the least amount of helper methods defined.
11
+ #
12
+ # @author Matheus Afonso Martins Moreira
13
+ # @since 0.8.0
14
+ # @see Ribbon
15
+ class Raw < BasicObject
16
+
17
+ # The hash used internally.
18
+ #
19
+ # @return [Hash] the hash used by this Ribbon instance to store data
20
+ # @api private
21
+ def __hash__
22
+ @hash ||= (::Hash.new &::Ribbon::Raw.default_value_proc)
23
+ end
24
+
25
+ # Initializes a new raw ribbon with the given values.
26
+ #
27
+ # If given a block, the raw ribbon will be yielded to it. If the block
28
+ # doesn't take any arguments, it will be evaluated in the context of the raw
29
+ # ribbon.
30
+ #
31
+ # All objects inside the hash will be {convert_all! converted}.
32
+ #
33
+ # @param [Ribbon, Ribbon::Raw, #to_hash] hash the hash with initial values
34
+ # @see CoreExtensions::BasicObject#__yield_or_eval__
35
+ def initialize(hash = {}, &block)
36
+ __hash__.merge! ::Ribbon.extract_hash_from hash
37
+ __yield_or_eval__ &block
38
+ ::Ribbon::Raw.convert_all! self
39
+ end
40
+
41
+ # Fetches the value associated with the given key.
42
+ #
43
+ # If given a block, the value will be yielded to it. If the block doesn't take
44
+ # any arguments, it will be evaluated in the context of the value.
45
+ #
46
+ # @param key the key which identifies the value
47
+ # @return the value associated with the given key
48
+ # @see CoreExtensions::BasicObject#__yield_or_eval__
49
+ def [](key, &block)
50
+ value = ::Ribbon::Raw.convert __hash__[key]
51
+ value.__yield_or_eval__ &block
52
+ self[key] = value
53
+ end
54
+
55
+ # Associates the given values with the given key.
56
+ #
57
+ # @param key the key that will identify the values
58
+ # @param values the values that will be associated with the key
59
+ # @raise [ArgumentError] if the given key is a raw ribbon
60
+ # @example
61
+ # ribbon = Ribbon.new
62
+ #
63
+ # ribbon[:key] = :value
64
+ # ribbon[:key]
65
+ # # => :value
66
+ #
67
+ # ribbon[:key] = :multiple, :values
68
+ # ribbon[:key]
69
+ # # => [:multiple, :values]
70
+ def []=(key, *values)
71
+ raise ArgumentError, 'Raw Ribbons can not be used as hash keys' if ::Ribbon.raw? key
72
+ __hash__[key] = if values.size == 1 then values.first else values end
73
+ end
74
+
75
+ # Handles the following cases:
76
+ #
77
+ # ribbon.method => ribbon[:method]
78
+ # ribbon.method value => ribbon[:method] = value
79
+ # ribbon.method &block => ribbon[:method, &block]
80
+ # ribbon.method value, &block => ribbon[:method] = value
81
+ # ribbon[:method, &block]
82
+ #
83
+ # ribbon.method = value => ribbon[:method] = value
84
+ #
85
+ # ribbon.method! value => ribbon[:method] = value
86
+ # self
87
+ # ribbon.method! &block => block.call ribbon[:method] if ribbon.__hash__.include? :method
88
+ # self
89
+ # ribbon.method! value, &block => ribbon[:method] = value
90
+ # block.call ribbon[:method]
91
+ # self
92
+ #
93
+ # ribbon.method? => ribbon.__hash__.fetch :method
94
+ # ribbon.method? value => ribbon.__hash__.fetch :method, value
95
+ # ribbon.method? &block => ribbon.__hash__.fetch :method, &block
96
+ # ribbon.method? value, &block => ribbon.__hash__.fetch :method, value, &block
97
+ def method_missing(method, *arguments, &block)
98
+ method_name = method.to_s
99
+ key = method_name.strip.gsub(/[=?!]$/, '').strip.intern
100
+ case method_name[-1]
101
+ when ?=
102
+ __send__ :[]=, key, *arguments
103
+ when ?!
104
+ __send__ :[]=, key, *arguments unless arguments.empty?
105
+ block.call self[key] if block and __hash__.include? key
106
+ self
107
+ when ??
108
+ begin __hash__.fetch key, *arguments, &block
109
+ rescue ::KeyError; nil end
110
+ else
111
+ __send__ :[]=, key, *arguments unless arguments.empty?
112
+ self[key, &block]
113
+ end
114
+ end
115
+
116
+ # Generates a simple and customizable human-readable string representation
117
+ # of this raw ribbon.
118
+ #
119
+ # @option options [#to_s] :separator (': ') separates the key/value pair
120
+ # @option options [#to_sym] :key (:to_s) will be sent to the key in order to
121
+ # convert it to a string.
122
+ # @option options [#to_sym] :value (:inspect) will be sent to the value in
123
+ # order to convert it to a string.
124
+ # @return [String] the string representation of this raw ribbon
125
+ def to_s(options = {})
126
+ __to_s_recursive__ ::Ribbon.extract_hash_from(options)
127
+ end
128
+
129
+ alias inspect to_s
130
+
131
+ private
132
+
133
+ # Computes a string value recursively for the given ribbon, and all ribbons
134
+ # inside it, using the given options.
135
+ #
136
+ # @see #to_s
137
+ def __to_s_recursive__(options = {}, ribbon = self)
138
+ ksym = options.fetch(:key, :to_s).to_sym
139
+ vsym = options.fetch(:value, :inspect).to_sym
140
+ separator = options.fetch(:separator, ': ').to_s
141
+ '{%s}' % ribbon.__hash__.map do |k, v|
142
+ k = k.__send__ ksym
143
+ v = v.raw if ::Ribbon === v
144
+ v = if ::Ribbon.raw? v then __to_s_recursive__ options, v
145
+ else v.__send__ vsym end
146
+ '%s%s%s' % [ k, separator, v ]
147
+ end.join(', ')
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ class << Ribbon::Raw
155
+
156
+ alias [] new
157
+
158
+ # Proc used to store a new {Ribbon ribbon} instance as the value of a missing
159
+ # key.
160
+ #
161
+ # @return [Proc] the proc used when constructing new hashes
162
+ def default_value_proc
163
+ @default_value_proc ||= (proc { |hash, key| hash[key] = Ribbon.new })
164
+ end
165
+
166
+ # Converts hashes to ribbons. Will look inside arrays.
167
+ #
168
+ # @param object the object to convert
169
+ # @return the converted value
170
+ def convert(object)
171
+ case object
172
+ when Hash then Ribbon.new object
173
+ when Array then object.map { |element| convert element }
174
+ else object
175
+ end
176
+ end
177
+
178
+ # Converts all values inside the given ribbon.
179
+ #
180
+ # @param [Ribbon, Ribbon::Raw] ribbon the ribbon whose values are to be
181
+ # converted
182
+ # @return [Ribbon, Ribbon::Raw] the ribbon with all values converted
183
+ # @see convert
184
+ def convert_all!(ribbon)
185
+ ribbon.__hash__.each do |key, value|
186
+ ribbon[key] = case value
187
+ when Ribbon then convert_all! value.raw
188
+ when Ribbon::Raw then convert_all! value
189
+ else convert value
190
+ end
191
+ end
192
+ ribbon
193
+ end
194
+
195
+ end
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ribbon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-24 00:00:00.000000000 Z
12
+ date: 2012-07-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jewel
@@ -98,7 +98,7 @@ files:
98
98
  - lib/ribbon/core_extensions/object/yield_or_eval.rb
99
99
  - lib/ribbon/gem.rb
100
100
  - lib/ribbon/options.rb
101
- - lib/ribbon/wrapper.rb
101
+ - lib/ribbon/raw.rb
102
102
  - ribbon.gemspec
103
103
  - ribbon.version
104
104
  homepage: https://github.com/matheusmoreira/ribbon
@@ -115,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
115
  version: '0'
116
116
  segments:
117
117
  - 0
118
- hash: -1868364444812272642
118
+ hash: 834480014355200814
119
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  none: false
121
121
  requirements:
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  version: '0'
125
125
  segments:
126
126
  - 0
127
- hash: -1868364444812272642
127
+ hash: 834480014355200814
128
128
  requirements: []
129
129
  rubyforge_project:
130
130
  rubygems_version: 1.8.24
@@ -1,224 +0,0 @@
1
- require 'ribbon'
2
-
3
- class Ribbon < BasicObject
4
-
5
- # Wraps a Ribbon in order to provide general-purpose methods.
6
- #
7
- # Ribbons are designed to use methods as hash keys. In order to maximize the
8
- # number of possibilities, many useful methods, including methods from Object,
9
- # were left out and included in this class instead.
10
- #
11
- # You can use wrapped ribbons like an ordinary hash. Any undefined methods
12
- # will be sent to the ribbon's hash. If the hash doesn't respond to the
13
- # method, it will be sent to the ribbon itself.
14
- #
15
- # wrapper = Ribbon::Wrapper.new
16
- #
17
- # wrapper.a.b.c
18
- # => {}
19
- # wrapper.keys
20
- # => [:a]
21
- #
22
- # Keep in mind that nested ribbons may or may not be wrapped:
23
- #
24
- # wrapper.a.b.c.keys
25
- # => {}
26
- # wrapper
27
- # => {a: {b: {c: {keys: {}}}}}
28
- #
29
- # You can wrap and unwrap all ribbons inside:
30
- #
31
- # wrapper.wrap_all!
32
- # wrapper.unwrap_all!
33
- # @author Matheus Afonso Martins Moreira
34
- # @since 0.2.0
35
- # @see Ribbon
36
- class Wrapper
37
-
38
- # The wrapped Ribbon.
39
- #
40
- # @return [Ribbon] the ribbon wrapped by this instance
41
- def ribbon
42
- @ribbon ||= Ribbon.new
43
- end
44
-
45
- # Wraps a Ribbon, another Wrapper's Ribbon or a hash.
46
- #
47
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] ribbon the ribbon that will be
48
- # wrapped
49
- # @return [Ribbon] the wrapped Ribbon
50
- def ribbon=(ribbon)
51
- @ribbon = case ribbon
52
- when Wrapper then ribbon.ribbon
53
- when Ribbon then ribbon
54
- else Ribbon.new ribbon.to_hash
55
- end
56
- end
57
-
58
- # Wraps the given Ribbon, another Wrapper's Ribbon or a hash.
59
- #
60
- # If given a block, the wrapper will be yielded to it. If the block doesn't
61
- # take any arguments, it will be evaluated in the context of the wrapper.
62
- #
63
- # @see #ribbon=
64
- # @see Ribbon#initialize
65
- def initialize(ribbon = Ribbon.new, &block)
66
- self.ribbon = ribbon
67
- __yield_or_eval__ &block
68
- end
69
-
70
- # The hash used by the wrapped Ribbon.
71
- #
72
- # @return [Hash] the internal hash of the Ribbon wrapped by this instance
73
- # @since 0.5.0
74
- def internal_hash
75
- ribbon.__hash__
76
- end
77
-
78
- # Forwards the method, arguments and block to the wrapped Ribbon's hash, if
79
- # it responds to the method, or to the ribbon itself otherwise.
80
- def method_missing(method, *args, &block)
81
- if (hash = internal_hash).respond_to? method then hash
82
- else ribbon end.__send__ method, *args, &block
83
- end
84
-
85
- # Merges the contents of this wrapped Ribbon with the contents of the given
86
- # Ribbon into a new Ribbon::Wrapper instance.
87
- #
88
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] ribbon the ribbon with new
89
- # values
90
- # @return [Ribbon::Wrapper] a new wrapped ribbon containing the results of
91
- # the merge
92
- # @yieldparam key the key which identifies both values
93
- # @yieldparam old_value the value from this wrapped Ribbon
94
- # @yieldparam new_value the value from the given ribbon
95
- # @yieldreturn the object that will be used as the new value
96
- # @since 0.4.5
97
- # @see #deep_merge!
98
- # @see Ribbon.deep_merge
99
- def deep_merge(ribbon, &block)
100
- Ribbon.wrap Ribbon.deep_merge(self, ribbon, &block)
101
- end
102
-
103
- # Merges this wrapped Ribbon with the given Ribbon.
104
- #
105
- # @param [Ribbon, Ribbon::Wrapper, #to_hash] ribbon the ribbon with new
106
- # values
107
- # @return [self] this Ribbon::Wrapper instance
108
- # @yieldparam key the key which identifies both values
109
- # @yieldparam old_value the value from this wrapped Ribbon
110
- # @yieldparam new_value the value from the given ribbon
111
- # @yieldreturn the object that will be used as the new value
112
- # @since 0.4.5
113
- # @see #deep_merge
114
- # @see Ribbon.deep_merge!
115
- def deep_merge!(ribbon, &block)
116
- Ribbon.deep_merge! self, ribbon, &block
117
- end
118
-
119
- # Wraps all ribbons contained by this wrapper's ribbon.
120
- #
121
- # @return [self] this Ribbon::Wrapper instance
122
- # @since 0.3.0
123
- def wrap_all!
124
- wrap_all_recursive!
125
- end
126
-
127
- # Unwraps all ribbons contained by this wrapper's ribbon.
128
- #
129
- # @return [Ribbon] the Ribbon wrapped by this instance
130
- # @since 0.3.0
131
- def unwrap_all!
132
- unwrap_all_recursive!
133
- end
134
-
135
- # Converts the wrapped Ribbon and all ribbons inside into hashes.
136
- #
137
- # @return [Hash] the converted contents of this wrapped Ribbon
138
- def to_hash
139
- to_hash_recursive
140
- end
141
-
142
- # Converts the wrapped ribbon to a hash and serializes it with YAML.
143
- #
144
- # @return [String] the YAML string that represents this Ribbon
145
- # @see from_yaml
146
- def to_yaml
147
- to_hash.to_yaml
148
- end
149
-
150
- # Delegates to the wrapped Ribbon.
151
- #
152
- # @return [String] the string representation of this Ribbon::Wrapper
153
- # @see Ribbon#to_s
154
- def to_s
155
- ribbon.to_s
156
- end
157
-
158
- private
159
-
160
- # Converts the wrapped ribbon and all ribbons inside into hashes using
161
- # recursion.
162
- #
163
- # @return [Hash] the converted contents of the wrapped Ribbon
164
- def to_hash_recursive(ribbon = self.ribbon)
165
- {}.tap do |hash|
166
- ribbon.__hash__.each do |key, value|
167
- hash[key] = case value
168
- when Ribbon then to_hash_recursive value
169
- when Ribbon::Wrapper then to_hash_recursive value.ribbon
170
- else value
171
- end
172
- end
173
- end
174
- end
175
-
176
- # Recursively wraps all ribbons and hashes inside.
177
- #
178
- # @return [self] this Ribbon::Wrapper instance
179
- # @since 0.3.0
180
- def wrap_all_recursive!(wrapper = self)
181
- (hash = wrapper.internal_hash).each do |key, value|
182
- hash[key] = case value
183
- when Ribbon, Hash then wrap_all_recursive! Ribbon::Wrapper[value]
184
- else value
185
- end
186
- end
187
- wrapper
188
- end
189
-
190
- # Recursively unwraps all wrapped ribbons inside.
191
- #
192
- # @return [Ribbon] the Ribbon wrapped by this instance
193
- # @since 0.3.0
194
- def unwrap_all_recursive!(ribbon = self.ribbon)
195
- ribbon.__hash__.each do |key, value|
196
- ribbon[key] = case value
197
- when Ribbon::Wrapper then unwrap_all_recursive! value.ribbon
198
- else value
199
- end
200
- end
201
- ribbon
202
- end
203
-
204
- end
205
-
206
- class << Wrapper
207
-
208
- # Wraps a Ribbon instance.
209
- #
210
- # @see #initialize
211
- alias [] new
212
-
213
- # Deserializes the hash from the +string+ using YAML and uses it to
214
- # construct a new wrapped ribbon.
215
- #
216
- # @return [Ribbon::Wrapper] a new wrapped Ribbon
217
- # @since 0.4.4
218
- # @see #to_yaml
219
- def from_yaml(string)
220
- ::Ribbon::Wrapper.new YAML.load(string)
221
- end
222
-
223
- end
224
- end