gibbler 0.8.10 → 0.10.0.pre.RC1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gibbler.rb CHANGED
@@ -1,40 +1,24 @@
1
- unless defined?(GIBBLER_LIB_HOME)
2
- GIBBLER_LIB_HOME = File.expand_path File.dirname(__FILE__)
3
- end
1
+ # frozen_string_literal: true
4
2
 
5
- %w{attic}.each do |dir|
6
- $:.unshift File.join(GIBBLER_LIB_HOME, '..', '..', dir, 'lib')
3
+ unless defined?(GIBBLER_LIB_HOME)
4
+ GIBBLER_LIB_HOME = File.expand_path File.dirname(__FILE__)
7
5
  end
8
-
9
- require 'thread'
10
- require 'attic'
11
6
  require 'digest/sha1'
12
7
 
13
- # = Gibbler
14
- #
8
+
9
+ # = Gibbler
10
+ #
15
11
  # "Hola, Tanneritos"
16
12
  #
17
- module Gibbler
18
- module VERSION
19
- def self.to_s
20
- load_config
21
- [@version[:MAJOR], @version[:MINOR], @version[:PATCH]].join('.')
22
- end
23
- alias_method :inspect, :to_s
24
- def self.load_config
25
- require 'yaml'
26
- @version ||= YAML.load_file(::File.join(GIBBLER_LIB_HOME, '..', 'VERSION.yml'))
27
- end
28
- end
29
-
13
+ class Gibbler < String
14
+
15
+
30
16
  @default_base = 16
31
17
  @secret = nil
32
18
  class << self
33
19
  attr_accessor :secret, :default_base
34
20
  end
35
-
36
- require 'gibbler/mixins'
37
-
21
+
38
22
  class Error < RuntimeError
39
23
  def initialize(obj); @obj = obj; end
40
24
  end
@@ -46,115 +30,118 @@ end
46
30
  # few digest related convenience methods.
47
31
  #
48
32
  class Gibbler::Digest < String
49
-
50
- # Return an integer assuming base is Gibbler.default_base.
51
- def to_i(base=nil)
52
- base ||= Gibbler.default_base
53
- super(base)
54
- end
55
-
56
- # Returns a string. Takes an optional base.
57
- def to_s(base=nil)
58
- base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
59
- end
60
-
61
- def base(base=Gibbler.default_base)
62
- self.class.new(self.to_i(Gibbler.default_base).to_s(base))
63
- end
64
-
65
- def base36
66
- base(36)
67
- end
68
-
69
- # Shorten the digest to the given (optional) length.
70
- def shorten(len=20)
71
- self[0..len-1]
72
- end
73
-
74
- # Returns the first 8 characters of itself (the digest).
75
- #
76
- # e.g.
77
- #
78
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
79
- # "kimmy".gibbler.short # => c8027100
80
- #
81
- def short
82
- shorten(8)
83
- end
84
-
85
- # Returns the first 6 characters of itself (the digest).
86
- #
87
- # e.g.
88
- #
89
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
90
- # "kimmy".gibbler.shorter # => c80271
91
- #
92
- def shorter
93
- shorten(6)
94
- end
95
-
96
- # Returns the first 4 characters of itself (the digest).
97
- #
98
- # e.g.
99
- #
100
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
101
- # "kimmy".gibbler.tiny # => c802
102
- #
103
- def tiny
104
- shorten(4)
105
- end
106
-
107
- # Returns true when +ali+ matches +self+
108
- #
109
- # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
110
- # "kimmy".gibbler == "c8027100" # => false
111
- #
112
- def ==(ali)
113
- return true if self.to_s == ali.to_s
114
- false
115
- end
116
-
117
- # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
118
- #
119
- # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
120
- # "kimmy".gibbler === "c8027100" # => true
121
- # "kimmy".gibbler === "c80271" # => true
122
- # "kimmy".gibbler === "c802" # => true
123
- #
124
- def ===(g)
125
- return true if [to_s, short, shorter, tiny].member?(g.to_s)
126
- false
33
+
34
+ module InstanceMethods
35
+ # Return an integer assuming base is Gibbler.default_base.
36
+ def to_i(base=nil)
37
+ base ||= Gibbler.default_base
38
+ super(base)
39
+ end
40
+
41
+ # Returns a string. Takes an optional base.
42
+ def to_s(base=nil)
43
+ base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
44
+ end
45
+
46
+ def base(base=Gibbler.default_base)
47
+ v = self.to_i(Gibbler.default_base).to_s(base)
48
+ v.extend Gibbler::Digest::InstanceMethods
49
+ self.class.new v
50
+ end
51
+
52
+ def base36
53
+ base(36)
54
+ end
55
+
56
+ # Shorten the digest to the given (optional) length.
57
+ def shorten(len=20)
58
+ self[0..len-1]
59
+ end
60
+
61
+ # Returns the first 8 characters of itself (the digest).
62
+ #
63
+ # e.g.
64
+ #
65
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
66
+ # "kimmy".gibbler.short # => c8027100
67
+ #
68
+ def short
69
+ shorten(8)
70
+ end
71
+
72
+ # Returns the first 6 characters of itself (the digest).
73
+ #
74
+ # e.g.
75
+ #
76
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
77
+ # "kimmy".gibbler.shorter # => c80271
78
+ #
79
+ def shorter
80
+ shorten(6)
81
+ end
82
+
83
+ # Returns the first 4 characters of itself (the digest).
84
+ #
85
+ # e.g.
86
+ #
87
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
88
+ # "kimmy".gibbler.tiny # => c802
89
+ #
90
+ def tiny
91
+ shorten(4)
92
+ end
93
+
94
+ # Returns true when +ali+ matches +self+
95
+ #
96
+ # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
97
+ # "kimmy".gibbler == "c8027100" # => false
98
+ #
99
+ def ==(ali)
100
+ return true if self.to_s == ali.to_s
101
+ false
102
+ end
103
+
104
+ # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
105
+ #
106
+ # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
107
+ # "kimmy".gibbler === "c8027100" # => true
108
+ # "kimmy".gibbler === "c80271" # => true
109
+ # "kimmy".gibbler === "c802" # => true
110
+ #
111
+ def ===(g)
112
+ return true if [to_s, short, shorter, tiny].member?(g.to_s)
113
+ false
114
+ end
127
115
  end
116
+ include InstanceMethods
128
117
  end
129
118
 
130
- module Gibbler
119
+ class Gibbler < String
131
120
  module Object
132
-
121
+
133
122
  def self.included(obj)
134
123
  obj.extend Attic
135
124
  obj.attic :gibbler_cache
136
- # Backwards compatibility for <= 0.6.2
137
- obj.send :alias_method, :__gibbler_cache, :gibbler_cache
138
125
  end
139
-
126
+
140
127
  def self.gibbler_fields
141
128
  end
142
129
  def gibbler_fields
143
130
  end
144
-
145
- # Calculates a digest for the current object instance.
131
+
132
+ # Calculates a digest for the current object instance.
146
133
  # Objects that are a kind of Hash or Array are processed
147
- # recursively. The length of the returned String depends
134
+ # recursively. The length of the returned String depends
148
135
  # on the digest type. Also stores the value in the attic.
149
- #
136
+ #
150
137
  # obj.gibbler # => a5b1191a
151
138
  # obj.gibbler_cache # => a5b1191a
152
- #
139
+ #
153
140
  # Calling gibbler_cache returns the most recent digest
154
141
  # without calculation.
155
142
  #
156
143
  # If the object is frozen, this will return the value of
157
- # <tt>gibbler_cache</tt>.
144
+ # `gibbler_cache`.
158
145
  #
159
146
  def gibbler(digest_type=nil)
160
147
  #gibbler_debug caller[0]
@@ -165,9 +152,9 @@ module Gibbler
165
152
 
166
153
  # Has this object been modified?
167
154
  #
168
- # This method compares the return value from digest with the
155
+ # This method compares the return value from digest with the
169
156
  # previous value returned by gibbler (the value is stored in
170
- # the attic as <tt>gibbler_cache</tt>).
157
+ # the attic as `gibbler_cache`).
171
158
  # See Attic[http://github.com/delano/attic]
172
159
  def gibbled?
173
160
  self.gibbler_cache ||= self.gibbler
@@ -180,15 +167,15 @@ module Gibbler
180
167
  return unless Gibbler.debug?
181
168
  p args
182
169
  end
183
-
170
+
184
171
  # Creates a digest for the current state of self based on:
185
172
  # * Object#class
186
173
  # * Length of Object#name || 0
187
174
  # * Object#name || ''
188
- #
189
- # e.g. Digest::SHA1.hexdigest "Class:6:Object" #=>
190
175
  #
191
- # <b>This is a default method appropriate for only the most
176
+ # e.g. Digest::SHA1.hexdigest "Class:6:Object" #=>
177
+ #
178
+ # <b>This is a default method appropriate for only the most
192
179
  # basic objects like Class and Module.</b>
193
180
  #
194
181
  def __gibbler(digest_type=nil)
@@ -199,10 +186,10 @@ module Gibbler
199
186
  gibbler_debug klass, a, [klass, nom.size, nom]
200
187
  a
201
188
  end
202
-
189
+
203
190
  # A simple override on Object#freeze to create a digest
204
191
  # before the object is frozen. Once the object is frozen
205
- # <tt>obj.gibbler</tt> will return the cached value with
192
+ # `obj.gibbler` will return the cached value with
206
193
  # out calculation.
207
194
  def freeze()
208
195
  gibbler_debug :FREEZE, self.class, caller[0] if Gibbler.debug?
@@ -210,52 +197,84 @@ module Gibbler
210
197
  super
211
198
  self
212
199
  end
213
-
200
+
201
+ end
202
+
203
+ end
204
+
205
+ class Gibbler < String
206
+ include Gibbler::Digest::InstanceMethods
207
+ # Modify the digest type for this instance. See Gibbler.digest_type
208
+ attr_writer :digest_type
209
+ attr_reader :input
210
+ # Creates a digest from the given +input+. See Gibbler.digest.
211
+ #
212
+ # If only one argument is given and it's a digest, this will
213
+ # simply create an instance of that digest. In other words,
214
+ # it won't calculate a new digest based on that input.
215
+ def initialize *input
216
+ if input.size == 1 && Gibbler::Digest::InstanceMethods === input.first
217
+ super input.first
218
+ else
219
+ input.collect!(&:to_s)
220
+ super Gibbler.digest(input) || ''
221
+ end
214
222
  end
215
-
223
+ def digest_type
224
+ @digest_type || self.class.digest_type
225
+ end
226
+
227
+ def digest *input
228
+ replace Gibbler.digest(input, digest_type)
229
+ end
230
+
216
231
  end
217
232
 
233
+ class Gibbler < String
218
234
 
219
- module Gibbler
235
+ @debug = false
236
+ @digest_type = ::Digest::SHA1
237
+ @delimiter = ':'
220
238
 
221
- @@gibbler_debug = false
222
- @@gibbler_digest_type = ::Digest::SHA1
223
-
224
- # Specify a different digest class. The default is +Digest::SHA1+. You
225
- # could try +Digest::SHA256+ by doing this:
226
- #
227
- # Object.gibbler_digest_type = Digest::SHA256
228
- #
229
- def self.digest_type=(v)
230
- @@gibbler_digest_type = v
239
+ class << self
240
+ # Specify a different digest class. The default is +Digest::SHA1+. You
241
+ # could try +Digest::SHA256+ by doing this:
242
+ #
243
+ # Object.digest_type = Digest::SHA256
244
+ #
245
+ attr_accessor :digest_type
246
+ # The delimiter to use when joining Array values before creating a
247
+ # new digest hash. The default is ":".
248
+ attr_accessor :delimiter
249
+ # Set to true for debug output (including all digest inputs)
250
+ attr_accessor :debug
251
+ # Returns the current debug status (true or false)
252
+ def debug?; @debug != false; end
231
253
  end
232
- # Returns the current debug status (true or false)
233
- def self.debug?; @@gibbler_debug; end
234
- def self.enable_debug; @@gibbler_debug = true; end
235
- def self.disable_debug; @@gibbler_debug = false; end
236
- def self.debug=(v); @@gibbler_debug = v; end
237
- # Returns the current digest class.
238
- def self.digest_type; @@gibbler_digest_type; end
239
-
240
- # Sends +str+ to Digest::SHA1.hexdigest. If another digest class
241
- # has been specified, that class will be used instead.
254
+
255
+ # Sends +input+ to Digest::SHA1.hexdigest. If another digest class
256
+ # has been specified, that class will be used instead.
242
257
  # If Gibbler.secret is set, +str+ will be prepended with the
243
- # value.
258
+ # value.
259
+ #
260
+ # If +input+ is an Array, it will be flattened and joined.
244
261
  #
245
262
  # See: digest_type
246
- def self.digest(str, digest_type=nil)
247
- digest_type ||= @@gibbler_digest_type
248
- str = [Gibbler.secret, str].join(':') unless Gibbler.secret.nil?
249
- dig = digest_type.hexdigest(str)
263
+ def self.digest(input, digest_type=nil)
264
+ input = input.flatten.collect(&:to_s).join(delimiter) if ::Array === input
265
+ return if input.empty?
266
+ digest_type ||= @digest_type
267
+ input = [Gibbler.secret, input].join(delimiter) unless Gibbler.secret.nil?
268
+ dig = digest_type.hexdigest(input)
250
269
  dig = dig.to_i(16).to_s(Gibbler.default_base) if 16 != Gibbler.default_base
251
270
  dig
252
271
  end
253
-
272
+
254
273
  def self.gibbler_debug(*args)
255
274
  return unless Gibbler.debug?
256
275
  p args
257
276
  end
258
-
277
+
259
278
  # Raises an exception. The correct usage is to include a Gibbler::Object:
260
279
  # * Gibbler::Complex
261
280
  # * Gibbler::String
@@ -264,19 +283,20 @@ module Gibbler
264
283
  def self.included(obj)
265
284
  raise "You probably want to include Gibbler::Complex or Gibbler::Object"
266
285
  end
267
-
268
- # Creates a digest based on:
269
- # * An Array of instance variable names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
270
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
286
+
287
+
288
+ # Creates a digest based on:
289
+ # * An Array of instance variable names or method names and values in the format: `CLASS:LENGTH:VALUE`
290
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
271
291
  # will be parsed recursively according to the gibbler method for that class type.
272
- # * Digest the Array of digests
273
- # * Return the digest for <tt>class:length:value</tt> where:
292
+ # * Digest the Array of digests
293
+ # * Return the digest for `class:length:value` where:
274
294
  # * "class" is equal to the current object class (e.g. FullHouse).
275
295
  # * "length" is the size of the Array of digests (which should equal
276
296
  # the number of instance variables in the object).
277
297
  # * "value" is the Array of digests joined with a colon (":").
278
298
  #
279
- # This method can be used by any class which stores values in instance variables.
299
+ # This method can be used by any class which stores values in instance variables.
280
300
  #
281
301
  # class Episodes
282
302
  # include Gibbler::Complex
@@ -285,7 +305,7 @@ module Gibbler
285
305
  #
286
306
  module Complex
287
307
  include Gibbler::Object
288
-
308
+
289
309
  def self.included(obj)
290
310
  obj.extend Attic
291
311
  obj.attic :gibbler_cache
@@ -307,7 +327,7 @@ module Gibbler
307
327
  end
308
328
  end
309
329
  end
310
-
330
+
311
331
  def gibbler_fields
312
332
  f = [self.class.gibbler_fields].compact.flatten
313
333
  if f.empty?
@@ -317,26 +337,26 @@ module Gibbler
317
337
  end
318
338
  f
319
339
  end
320
-
321
- # Creates a digest for the current state of self.
340
+
341
+ # Creates a digest for the current state of self.
322
342
  def __gibbler(digest_type=nil)
323
343
  klass = self.class
324
344
  d = []
325
345
  gibbler_debug :gibbler_fields, gibbler_fields
326
346
  gibbler_fields.each do |n|
327
- value = instance_variable_get("@#{n}")
347
+ value = respond_to?(n) ? send(n) : instance_variable_get("@#{n}")
328
348
  unless value.respond_to? :__gibbler
329
349
  gibbler_debug klass, :skipping, n
330
350
  next
331
351
  end
332
352
  d << '%s:%s:%s' % [value.class, n, value.__gibbler(digest_type)]
333
353
  end
334
- d = d.join(':').__gibbler(digest_type)
354
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
335
355
  a = Gibbler.digest "%s:%d:%s" % [klass, d.size, d], digest_type
336
356
  gibbler_debug klass, a, [klass, d.size, d]
337
357
  a
338
358
  end
339
-
359
+
340
360
  def __gibbler_revert!
341
361
  state = self.gibbler_object self.gibbler_cache
342
362
  state.instance_variables do |n|
@@ -344,33 +364,32 @@ module Gibbler
344
364
  self.instance_variable_set v
345
365
  end
346
366
  end
347
-
348
367
  end
349
-
350
- # Creates a digest based on: <tt>CLASS:LENGTH:VALUE</tt>.
351
- # This method can be used for any class where the <tt>to_s</tt>
352
- # method returns an appropriate unique value for this instance.
353
- # It's used by default for Symbol, Class, Fixnum, and Bignum.
368
+
369
+ # Creates a digest based on: `CLASS:LENGTH:VALUE`.
370
+ # This method can be used for any class where the `to_s`
371
+ # method returns an appropriate unique value for this instance.
372
+ # It's used by default for Symbol, Class, Integer.
354
373
  # e.g.
355
- #
374
+ #
356
375
  # "str" => String:3:str => 509a839ca1744c72e37759e7684ff0daa3b61427
357
376
  # :sym => Symbol:3:sym => f3b7b3ca9529002c6826b1ef609d3583c356c8c8
358
377
  #
359
378
  # To use use method in other classes simply:
360
379
  #
361
- # class MyStringLikeClass
380
+ # class MyStringLikeClass
362
381
  # include Gibbler::String
363
382
  # end
364
383
  #
365
384
  module String
366
385
  include Gibbler::Object
367
-
386
+
368
387
  def self.included(obj)
369
388
  obj.extend Attic
370
389
  obj.attic :gibbler_cache
371
390
  end
372
-
373
- # Creates a digest for the current state of self.
391
+
392
+ # Creates a digest for the current state of self.
374
393
  def __gibbler(digest_type=nil)
375
394
  klass = self.class
376
395
  value = self.nil? ? "\0" : self.to_s
@@ -379,81 +398,81 @@ module Gibbler
379
398
  a
380
399
  end
381
400
  end
382
-
383
- # Creates a digest based on:
384
- # * parse each key, value pair into an Array containing keys: <tt>CLASS:KEY:VALUE.__gibbler</tt>
385
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
401
+
402
+ # Creates a digest based on:
403
+ # * parse each key, value pair into an Array containing keys: `CLASS:KEY:VALUE.__gibbler`
404
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
386
405
  # will be parsed recursively according to the gibbler method for that class type.
387
- # * Digest the Array of digests
388
- # * Return the digest for <tt>class:length:value</tt> where:
406
+ # * Digest the Array of digests
407
+ # * Return the digest for `class:length:value` where:
389
408
  # * "class" is equal to the current object class (e.g. Hash).
390
409
  # * "length" is the size of the Array of digests (which should equal
391
410
  # the number of keys in the original Hash object).
392
411
  # * "value" is the Array of digests joined with a colon (":").
393
412
  #
394
- # This method can be used by any class with a <tt>keys</tt> method.
413
+ # This method can be used by any class with a `keys` method.
395
414
  #
396
415
  # class MyOrderedHash
397
416
  # include Gibbler::Hash
398
417
  # end
399
418
  #
400
- module Hash
419
+ module Hash
401
420
  include Gibbler::Object
402
-
421
+
403
422
  def self.included(obj)
404
423
  obj.extend Attic
405
424
  obj.attic :gibbler_cache
406
425
  end
407
-
408
- # Creates a digest for the current state of self.
426
+
427
+ # Creates a digest for the current state of self.
409
428
  def __gibbler(digest_type=nil)
410
429
  klass = self.class
411
430
  d = self.keys.sort { |a,b| a.inspect <=> b.inspect }
412
- d.collect! do |name|
431
+ d.collect! do |name|
413
432
  value = self[name]
414
433
  unless value.respond_to? :__gibbler
415
434
  gibbler_debug klass, :skipping, name
416
435
  next
417
436
  end
418
437
  '%s:%s:%s' % [value.class, name, value.__gibbler(digest_type)]
419
- end
420
- d = d.join(':').__gibbler(digest_type)
438
+ end
439
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
421
440
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
422
441
  gibbler_debug klass, a, [klass, d.size, d]
423
- a
442
+ a
424
443
  end
425
444
  end
426
-
445
+
427
446
  # Creates a digest based on:
428
- # * parse each element into an Array of digests like: <tt>CLASS:INDEX:VALUE.__gibbler</tt>
429
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
430
- # will be parsed recursively according to the gibbler method for that class type.
431
- # * Digest the Array of digests
432
- # * Return the digest for <tt>class:length:value</tt> where:
447
+ # * parse each element into an Array of digests like: `CLASS:INDEX:VALUE.__gibbler`
448
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
449
+ # will be parsed recursively according to the gibbler method for that class type.
450
+ # * Digest the Array of digests
451
+ # * Return the digest for `class:length:value` where:
433
452
  # * "class" is equal to the current object class (e.g. Array).
434
453
  # * "length" is the size of the Array of digests (which should equal
435
454
  # the number of elements in the original Array object).
436
455
  # * "value" is the Array of digests joined with a colon (":").
437
456
  #
438
- # This method can be used by any class with an <tt>each</tt> method.
457
+ # This method can be used by any class with an `each` method.
439
458
  #
440
- # class MyNamedArray
459
+ # class MyNamedArray
441
460
  # include Gibbler::Array
442
461
  # end
443
462
  #
444
463
  module Array
445
464
  include Gibbler::Object
446
-
465
+
447
466
  def self.included(obj)
448
467
  obj.extend Attic
449
468
  obj.attic :gibbler_cache
450
469
  end
451
-
452
- # Creates a digest for the current state of self.
470
+
471
+ # Creates a digest for the current state of self.
453
472
  def __gibbler(digest_type=nil)
454
473
  klass = self.class
455
474
  d, index = [], 0
456
- self.each_with_index do |value,idx|
475
+ self.each_with_index do |value,idx|
457
476
  unless value.respond_to? :__gibbler
458
477
  gibbler_debug klass, :skipping, idx
459
478
  next
@@ -461,35 +480,35 @@ module Gibbler
461
480
  d << '%s:%s:%s' % [value.class, index, value.__gibbler(digest_type)]
462
481
  index += 1
463
482
  end
464
- d = d.join(':').__gibbler(digest_type)
483
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
465
484
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
466
485
  gibbler_debug klass, a, [klass, d.size, d]
467
486
  a
468
487
  end
469
488
  end
470
-
471
- # Creates a digest based on: <tt>CLASS:LENGTH:TIME</tt>.
472
- # Times are calculated based on the equivalent time in UTC.
489
+
490
+ # Creates a digest based on: `CLASS:LENGTH:TIME`.
491
+ # Times are calculated based on the equivalent time in UTC.
473
492
  # e.g.
474
- #
493
+ #
475
494
  # Time.parse('2009-08-25 16:43:53 UTC') => 73b4635f
476
495
  # Time.parse('2009-08-25 12:43:53 -04:00') => 73b4635f
477
496
  #
478
497
  # To use use method in other classes simply:
479
498
  #
480
- # class ClassLikeTime
499
+ # class ClassLikeTime
481
500
  # include Gibbler::Time
482
501
  # end
483
502
  #
484
503
  module Time
485
504
  include Gibbler::Object
486
-
505
+
487
506
  def self.included(obj)
488
507
  obj.extend Attic
489
508
  obj.attic :gibbler_cache
490
509
  end
491
-
492
- # Creates a digest for the current state of self.
510
+
511
+ # Creates a digest for the current state of self.
493
512
  def __gibbler(digest_type=nil)
494
513
  klass = self.class
495
514
  value = self.nil? ? "\0" : self.utc.strftime('%Y-%m-%d %H:%M:%S UTC')
@@ -498,29 +517,29 @@ module Gibbler
498
517
  a
499
518
  end
500
519
  end
501
-
502
- # Creates a digest based on: <tt>CLASS:LENGTH:DATETIME</tt>.
503
- # Dates are calculated based on the equivalent datetime in UTC.
520
+
521
+ # Creates a digest based on: `CLASS:LENGTH:DATETIME`.
522
+ # Dates are calculated based on the equivalent datetime in UTC.
504
523
  # e.g.
505
- #
524
+ #
506
525
  # DateTime.parse('2009-08-25T17:00:40+00:00') => ad64c769
507
526
  # DateTime.parse('2009-08-25T13:00:40-04:00') => ad64c769
508
527
  #
509
528
  # To use use method in other classes simply:
510
529
  #
511
- # class ClassLikeTime
530
+ # class ClassLikeTime
512
531
  # include Gibbler::Time
513
532
  # end
514
533
  #
515
534
  module DateTime
516
535
  include Gibbler::Object
517
-
536
+
518
537
  def self.included(obj)
519
538
  obj.extend Attic
520
539
  obj.attic :gibbler_cache
521
540
  end
522
-
523
- # Creates a digest for the current state of self.
541
+
542
+ # Creates a digest for the current state of self.
524
543
  def __gibbler(digest_type=nil)
525
544
  klass = self.class
526
545
  value = self.nil? ? "\0" : self.new_offset(0).to_s
@@ -528,36 +547,36 @@ module Gibbler
528
547
  gibbler_debug klass, a, [klass, value.size, value]
529
548
  a
530
549
  end
531
-
550
+
532
551
  end
533
-
534
- # Creates a digest based on: <tt>CLASS:EXCLUDE?:FIRST:LAST</tt>
552
+
553
+ # Creates a digest based on: `CLASS:EXCLUDE?:FIRST:LAST`
535
554
  # where EXCLUDE? is a boolean value whether the Range excludes
536
555
  # the last value (i.e. 1...100) and FIRST and LAST are the values
537
556
  # returned by Range#first and Range#last.
538
557
  # e.g.
539
- #
558
+ #
540
559
  # (1..100) => Range:false:1:100 => 54506352
541
560
  # (1...100) => Range:true:1:100 => f0cad8cc
542
561
  #
543
562
  # To use use method in other classes simply:
544
563
  #
545
- # class ClassLikeRange
564
+ # class ClassLikeRange
546
565
  # include Gibbler::Range
547
566
  # end
548
567
  #
549
568
  module Range
550
569
  include Gibbler::Object
551
-
570
+
552
571
  def self.included(obj)
553
572
  obj.extend Attic
554
573
  obj.attic :gibbler_cache
555
574
  end
556
-
557
- # Creates a digest for the current state of self.
575
+
576
+ # Creates a digest for the current state of self.
558
577
  def __gibbler(digest_type=nil)
559
578
  klass = self.class
560
- if self.nil?
579
+ if self.nil?
561
580
  first, last, exclude = "\0", "\0", "\0"
562
581
  else
563
582
  first, last, exclude = self.first, self.last, self.exclude_end?
@@ -566,10 +585,10 @@ module Gibbler
566
585
  gibbler_debug klass, a, [klass, exclude, first, last]
567
586
  a
568
587
  end
569
-
588
+
570
589
  end
571
-
572
- # Creates a digest based on: <tt>CLASS:\0</tt>
590
+
591
+ # Creates a digest based on: `CLASS:\0`
573
592
  #
574
593
  # e.g.
575
594
  #
@@ -583,7 +602,7 @@ module Gibbler
583
602
  obj.attic :gibbler_cache
584
603
  end
585
604
 
586
- # Creates a digest for the current state of self.
605
+ # Creates a digest for the current state of self.
587
606
  def __gibbler(digest_type=nil)
588
607
  klass = self.class
589
608
  a = Gibbler.digest "%s:%s" % [klass, "\0"], digest_type
@@ -591,34 +610,34 @@ module Gibbler
591
610
  a
592
611
  end
593
612
  end
594
-
595
- # Creates a digest based on: <tt>CLASS:PATHLENGTH:PATH</tt>
613
+
614
+ # Creates a digest based on: `CLASS:PATHLENGTH:PATH`
596
615
  # where PATHLENGTH is the length of the PATH string. PATH is
597
616
  # not modified in any way (it is not converted to an absolute
598
- # path).
599
- #
617
+ # path).
618
+ #
600
619
  # NOTE: You may expect this method to include other information
601
620
  # like the file contents and modified date (etc...). The reason
602
621
  # we do not is because Gibbler is concerned only about Ruby and
603
622
  # not the outside world. There are many complexities in parsing
604
623
  # file data and attributes which would make it difficult to run
605
- # across platforms and Ruby versions / engines. If you want to
624
+ # across platforms and Ruby versions / engines. If you want to
606
625
  #
607
626
  # e.g.
608
- #
627
+ #
609
628
  # File.new('.') # => c8bc8b3a
610
629
  # File.new('/tmp') # => 3af85a19
611
630
  # File.new('/tmp/') # => 92cbcb7d
612
- #
631
+ #
613
632
  module File
614
633
  include Gibbler::Object
615
-
634
+
616
635
  def self.included(obj)
617
636
  obj.extend Attic
618
637
  obj.attic :gibbler_cache
619
638
  end
620
-
621
- # Creates a digest for the current state of self.
639
+
640
+ # Creates a digest for the current state of self.
622
641
  def __gibbler(digest_type=nil)
623
642
  klass = self.class
624
643
  value = self.nil? ? "\0" : self.path
@@ -627,59 +646,13 @@ module Gibbler
627
646
  a
628
647
  end
629
648
  end
630
-
631
- ##--
632
- ## NOTE: this was used when Gibbler supported "include Gibbler". We
633
- ## now recommend the "include Gibbler::String" approach. This was an
634
- ## interesting approach so I'm keeping the code here for reference.
635
- ##def self.included(klass)
636
- ## # Find the appropriate Gibbler::* module for the inheriting class
637
- ## gibbler_module = Gibbler.const_get("#{klass}") rescue Gibbler::String
638
- ##
639
- ## # If a Gibbler module is not defined, const_get bubbles up
640
- ## # through the stack to find the constant. This will return
641
- ## # the global class (likely itself) so we enforce a default.
642
- ## gibbler_module = Gibbler::String if gibbler_module == klass
643
- ## gibbler_debug :constant, klass, gibbler_module
644
- ##
645
- ## klass.module_eval do
646
- ## include gibbler_module
647
- ## end
648
- ##
649
- ##end
650
- ##++
651
-
652
-
653
- end
654
-
655
-
656
- class NilClass; include Gibbler::Nil; end
657
- class Class; include Gibbler::Object; end
658
- class Module; include Gibbler::Object; end
659
- class Proc; include Gibbler::Object; end
660
- class String; include Gibbler::String; end
661
- class Regexp; include Gibbler::String; end
662
- class Fixnum; include Gibbler::String; end
663
- class Bignum; include Gibbler::String; end
664
- class TrueClass; include Gibbler::String; end
665
- class FalseClass; include Gibbler::String; end
666
- class Float; include Gibbler::String; end
667
- class Symbol; include Gibbler::String; end
668
- class Date; include Gibbler::String; end
669
- class Hash; include Gibbler::Hash; end
670
- class Array; include Gibbler::Array; end
671
- class Time; include Gibbler::Time; end
672
- class DateTime < Date; include Gibbler::DateTime; end
673
- class Range; include Gibbler::Range; end
674
- class File; include Gibbler::File; end
675
- class TempFile; include Gibbler::File; end
676
-
677
- # URI::Generic must be included towards the
678
- # end b/c it runs Object#freeze statically.
679
- module URI; class Generic; include Gibbler::String; end; end
680
-
681
- # Bundler calls freeze on an instance of Gem::Platform
682
- module Gem; class Platform; include Gibbler::Complex; end; end
683
-
684
649
 
650
+ end
685
651
 
652
+ class String
653
+ unless method_defined? :clear
654
+ def clear
655
+ replace ""
656
+ end
657
+ end
658
+ end