frivol 0.1.4 → 0.1.5
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.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/doc/classes/Frivol.html +38 -70
- data/doc/classes/Frivol.src/M000003.html +4 -4
- data/doc/classes/Frivol.src/M000004.html +3 -3
- data/doc/classes/Frivol.src/M000005.html +4 -5
- data/doc/classes/Frivol.src/M000006.html +5 -4
- data/doc/classes/Frivol.src/M000007.html +19 -0
- data/doc/classes/Frivol/ClassMethods.html +62 -26
- data/doc/classes/Frivol/ClassMethods.src/M000008.html +5 -4
- data/doc/classes/Frivol/ClassMethods.src/M000009.html +19 -0
- data/doc/classes/Frivol/ClassMethods.src/M000010.html +53 -0
- data/doc/classes/Frivol/Config.html +15 -43
- data/doc/classes/Frivol/Config.src/M000011.html +4 -5
- data/doc/classes/Frivol/Config.src/M000012.html +18 -0
- data/doc/classes/Frivol/Config.src/M000013.html +19 -0
- data/doc/classes/Time.html +4 -25
- data/doc/classes/Time.src/M000001.html +1 -1
- data/doc/classes/Time.src/M000002.html +1 -1
- data/doc/created.rid +1 -1
- data/doc/files/lib/frivol_rb.html +35 -6
- data/doc/fr_method_index.html +4 -3
- data/doc/index.html +2 -2
- data/frivol.gemspec +10 -5
- data/lib/frivol.rb +152 -32
- data/test/fake_redis.rb +5 -1
- data/test/test_frivol.rb +137 -5
- metadata +13 -8
data/lib/frivol.rb
CHANGED
@@ -28,6 +28,21 @@
|
|
28
28
|
# The <tt>expire_storage(time)</tt> method can be used to set the expiry time in seconds of the temporary storage.
|
29
29
|
# The default is not to expire the storage, in which case it will live for as long as Redis keeps it.
|
30
30
|
# <tt>delete_storage</tt>, as the name suggests will immediately delete the storage.
|
31
|
+
#
|
32
|
+
# Since version 0.1.5 Frivol can create different storage buckets. Note that this introduces a breaking change
|
33
|
+
# to the <tt>storage_key</tt> method if you have overriden it. It now takes a +bucket+ parameter.
|
34
|
+
#
|
35
|
+
# Buckets can have their own expiry time and there are special counter buckets which simply keep an integer count.
|
36
|
+
#
|
37
|
+
# storage_bucket :my_bucket, :expires_in => 5.minutes
|
38
|
+
# storage_bucket :my_counter, :counter => true
|
39
|
+
#
|
40
|
+
# Given the above, Frivol will create <tt>store_my_bucket</tt> and <tt>retrieve_my_bucket</tt> methods which work
|
41
|
+
# exactly like the standard +store+ and +retrieve+ methods. There will also be <tt>store_my_counter</tt>,
|
42
|
+
# <tt>retrieve_my_counter</tt> and <tt>increment_my_counter</tt> methods. The counter store and retrieve only
|
43
|
+
# take a integer (value and default, respectively) and the increment does not take a parameter.
|
44
|
+
#
|
45
|
+
# These methods are thread safe if you pass <tt>:thread_safe => true</tt> to the Redis configuration.
|
31
46
|
#
|
32
47
|
# Frivol uses the +storage_key+ method to create a base key for storage in Redis. The current implementation uses
|
33
48
|
# <tt>"#{self.class.name}-#{id}"</tt> so you'll want to override that method if you have classes that don't
|
@@ -44,8 +59,8 @@
|
|
44
59
|
# @key = key
|
45
60
|
# end
|
46
61
|
#
|
47
|
-
# def storage_key
|
48
|
-
# "frivol-test-#{key}" # override the storage key because we don't respond_to? id
|
62
|
+
# def storage_key(bucket = nil)
|
63
|
+
# "frivol-test-#{key}" # override the storage key because we don't respond_to? :id, and don't care about buckets
|
49
64
|
# end
|
50
65
|
#
|
51
66
|
# def big_complex_calc
|
@@ -69,6 +84,9 @@ require "redis"
|
|
69
84
|
|
70
85
|
# == Frivol
|
71
86
|
module Frivol
|
87
|
+
# Defines a constant to indicate that storage should never expire
|
88
|
+
NEVER_EXPIRE = nil
|
89
|
+
|
72
90
|
# Store a hash of keys and values.
|
73
91
|
#
|
74
92
|
# The hash need not be the complete hash of all things stored, just those you want to change.
|
@@ -77,11 +95,11 @@ module Frivol
|
|
77
95
|
# is intended to be hidden and while it is true that it currently uses a <tt>Hash#to_json</tt> you should not
|
78
96
|
# rely on this.
|
79
97
|
def store(keys_and_values)
|
80
|
-
Frivol::Helpers.retrieve_hash
|
98
|
+
hash = Frivol::Helpers.retrieve_hash(self)
|
81
99
|
keys_and_values.each do |key, value|
|
82
|
-
|
100
|
+
hash[key.to_s] = value
|
83
101
|
end
|
84
|
-
Frivol::Helpers.store_hash
|
102
|
+
Frivol::Helpers.store_hash(self, hash)
|
85
103
|
end
|
86
104
|
|
87
105
|
# Retrieve stored values, or defaults.
|
@@ -94,9 +112,9 @@ module Frivol
|
|
94
112
|
# If the default is a symbol, Frivol will attempt to get the default from a method named after that symbol.
|
95
113
|
# If the class does not <tt>respond_to?</tt> a method by that name, the symbol will assumed to be the default.
|
96
114
|
def retrieve(keys_and_defaults)
|
97
|
-
Frivol::Helpers.retrieve_hash
|
115
|
+
hash = Frivol::Helpers.retrieve_hash(self)
|
98
116
|
result = keys_and_defaults.map do |key, default|
|
99
|
-
|
117
|
+
hash[key.to_s] || (default.is_a?(Symbol) && respond_to?(default) && send(default)) || default
|
100
118
|
end
|
101
119
|
return result.first if result.size == 1
|
102
120
|
result
|
@@ -108,18 +126,22 @@ module Frivol
|
|
108
126
|
end
|
109
127
|
|
110
128
|
# Expire the stored data in +time+ seconds.
|
111
|
-
def expire_storage(time)
|
129
|
+
def expire_storage(time, bucket = nil)
|
112
130
|
return if time.nil?
|
113
|
-
Frivol::Config.redis.expire storage_key, time
|
131
|
+
Frivol::Config.redis.expire storage_key(bucket), time
|
114
132
|
end
|
115
133
|
|
116
134
|
# The base key used for storage in Redis.
|
117
135
|
#
|
118
|
-
# This method has been implemented for use with ActiveRecord and uses <tt>"#{self.class.name}-#{id}"</tt>
|
136
|
+
# This method has been implemented for use with ActiveRecord and uses <tt>"#{self.class.name}-#{id}"</tt>
|
137
|
+
# for the default bucket and <tt>"#{self.class.name}-#{id}-#{bucket}"</tt> for a named bucket.
|
119
138
|
# If you are not using ActiveRecord, or using classes that don't respond to id, you should override
|
120
139
|
# this method in your class.
|
121
|
-
|
140
|
+
#
|
141
|
+
# NOTE: This method has changed since version 0.1.4, and now has the bucket parameter (default: nil)
|
142
|
+
def storage_key(bucket = nil)
|
122
143
|
@frivol_key ||= "#{self.class.name}-#{id}"
|
144
|
+
bucket.nil? ? @frivol_key : "#{@frivol_key}-#{bucket}"
|
123
145
|
end
|
124
146
|
|
125
147
|
# == Frivol::Config
|
@@ -156,46 +178,144 @@ module Frivol
|
|
156
178
|
end
|
157
179
|
|
158
180
|
module Helpers #:nodoc:
|
159
|
-
def self.store_hash(instance)
|
160
|
-
|
161
|
-
|
162
|
-
|
181
|
+
def self.store_hash(instance, hash, bucket = nil)
|
182
|
+
data, is_new = get_hash_and_is_new(instance, bucket)
|
183
|
+
data[bucket.to_s] = hash
|
184
|
+
|
185
|
+
key = instance.send(:storage_key, bucket)
|
163
186
|
Frivol::Config.redis[key] = hash.to_json
|
164
|
-
|
165
|
-
|
166
|
-
instance.
|
187
|
+
|
188
|
+
if is_new[bucket.to_s]
|
189
|
+
time = instance.class.storage_expiry(bucket)
|
190
|
+
Frivol::Config.redis.expire(key, time) if time != Frivol::NEVER_EXPIRE
|
191
|
+
is_new[bucket.to_s] = false
|
167
192
|
end
|
168
193
|
end
|
169
194
|
|
170
|
-
def self.retrieve_hash(instance)
|
171
|
-
|
172
|
-
|
195
|
+
def self.retrieve_hash(instance, bucket = nil)
|
196
|
+
data, is_new = get_hash_and_is_new(instance, bucket)
|
197
|
+
return data[bucket.to_s] if data.key?(bucket.to_s)
|
198
|
+
key = instance.send(:storage_key, bucket)
|
173
199
|
json = Frivol::Config.redis[key]
|
174
|
-
|
200
|
+
|
201
|
+
is_new[bucket.to_s] = json.nil?
|
202
|
+
instance.instance_variable_set :@frivol_is_new, is_new
|
203
|
+
|
175
204
|
hash = json.nil? ? {} : JSON.parse(json)
|
176
|
-
|
205
|
+
data[bucket.to_s] = hash
|
206
|
+
instance.instance_variable_set :@frivol_data, data
|
207
|
+
|
177
208
|
hash
|
178
209
|
end
|
179
210
|
|
180
|
-
def self.delete_hash(instance)
|
181
|
-
key = instance.send(:storage_key)
|
211
|
+
def self.delete_hash(instance, bucket = nil)
|
212
|
+
key = instance.send(:storage_key, bucket)
|
182
213
|
Frivol::Config.redis.del key
|
183
|
-
|
214
|
+
|
215
|
+
data = instance.instance_variable_defined?(:@frivol_data) ? instance.instance_variable_get(:@frivol_data) : {}
|
216
|
+
data.delete(bucket.to_s)
|
217
|
+
instance.instance_variable_set :@frivol_data, data
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.get_hash_and_is_new(instance, bucket)
|
221
|
+
data = instance.instance_variable_defined?(:@frivol_data) ? instance.instance_variable_get(:@frivol_data) : {}
|
222
|
+
is_new = instance.instance_variable_defined?(:@frivol_is_new) ? instance.instance_variable_get(:@frivol_is_new) : {}
|
223
|
+
[data, is_new]
|
224
|
+
end
|
225
|
+
|
226
|
+
def self.store_counter(instance, counter, value)
|
227
|
+
key = instance.send(:storage_key, counter)
|
228
|
+
Frivol::Config.redis[key] = value
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.retrieve_counter(instance, counter, default)
|
232
|
+
key = instance.send(:storage_key, counter)
|
233
|
+
(Frivol::Config.redis[key] || default).to_i
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.increment_counter(instance, counter)
|
237
|
+
key = instance.send(:storage_key, counter)
|
238
|
+
Frivol::Config.redis.incr(key)
|
184
239
|
end
|
185
240
|
end
|
186
241
|
|
187
242
|
# == Frivol::ClassMethods
|
188
243
|
# These methods are available on the class level when Frivol is included in the class.
|
189
244
|
module ClassMethods
|
190
|
-
# Set the storage expiry time in seconds.
|
191
|
-
def storage_expires_in(time)
|
192
|
-
@frivol_storage_expiry
|
245
|
+
# Set the storage expiry time in seconds for the default bucket or the bucket passed.
|
246
|
+
def storage_expires_in(time, bucket = nil)
|
247
|
+
@frivol_storage_expiry ||= {}
|
248
|
+
@frivol_storage_expiry[bucket.to_s] = time
|
193
249
|
end
|
194
250
|
|
195
|
-
# Get the storage expiry time in seconds.
|
196
|
-
def storage_expiry
|
197
|
-
@frivol_storage_expiry
|
251
|
+
# Get the storage expiry time in seconds for the default bucket or the bucket passed.
|
252
|
+
def storage_expiry(bucket = nil)
|
253
|
+
@frivol_storage_expiry ||= {}
|
254
|
+
@frivol_storage_expiry.key?(bucket.to_s) ? @frivol_storage_expiry[bucket.to_s] : NEVER_EXPIRE
|
198
255
|
end
|
256
|
+
|
257
|
+
# Create a storage bucket.
|
258
|
+
# Frivol creates store_#{bucket} and retrieve_#{bucket} methods automatically.
|
259
|
+
# These methods work exactly like the default store and retrieve methods except that the bucket is
|
260
|
+
# stored in it's own key in Redis and can have it's own expiry time.
|
261
|
+
#
|
262
|
+
# Counters are special in that they do not store a hash but only a single integer value and also
|
263
|
+
# that the data in a counter is not cached for the lifespan of the object, but rather each call
|
264
|
+
# hits Redis. This is intended to make counters thread safe (for example you may have multiple
|
265
|
+
# workers working on a job and they can each increment a progress counter which would not work
|
266
|
+
# with the default retrieve/store method that normal buckets use). For this to actually be thread safe
|
267
|
+
# you need to pass the thread safe option to the config when you make the connection.
|
268
|
+
#
|
269
|
+
# In the case of a counter, the methods work slightly differently:
|
270
|
+
# - store_#{bucket} only takes an integer value to store (no key)
|
271
|
+
# - retrieve_#{bucket} only takes an integer default, and returns only the integer value
|
272
|
+
# - there is an added increment_#{bucket} method which increments the counter by 1
|
273
|
+
#
|
274
|
+
# Options are :expires_in which sets the expiry time for a bucket,
|
275
|
+
# and :counter to create a special counter storage bucket.
|
276
|
+
def storage_bucket(bucket, options = {})
|
277
|
+
time = options[:expires_in]
|
278
|
+
storage_expires_in(time, bucket) if !time.nil?
|
279
|
+
is_counter = options[:counter]
|
280
|
+
|
281
|
+
self.class_eval do
|
282
|
+
if is_counter
|
283
|
+
define_method "store_#{bucket}" do |value|
|
284
|
+
Frivol::Helpers.store_counter(self, bucket, value)
|
285
|
+
end
|
286
|
+
|
287
|
+
define_method "retrieve_#{bucket}" do |default|
|
288
|
+
Frivol::Helpers.retrieve_counter(self, bucket, default)
|
289
|
+
end
|
290
|
+
|
291
|
+
define_method "increment_#{bucket}" do
|
292
|
+
Frivol::Helpers.increment_counter(self, bucket)
|
293
|
+
end
|
294
|
+
else
|
295
|
+
define_method "store_#{bucket}" do |keys_and_values|
|
296
|
+
hash = Frivol::Helpers.retrieve_hash(self, bucket)
|
297
|
+
keys_and_values.each do |key, value|
|
298
|
+
hash[key.to_s] = value
|
299
|
+
end
|
300
|
+
Frivol::Helpers.store_hash(self, hash, bucket)
|
301
|
+
end
|
302
|
+
|
303
|
+
define_method "retrieve_#{bucket}" do |keys_and_defaults|
|
304
|
+
hash = Frivol::Helpers.retrieve_hash(self, bucket)
|
305
|
+
result = keys_and_defaults.map do |key, default|
|
306
|
+
hash[key.to_s] || (default.is_a?(Symbol) && respond_to?(default) && send(default)) || default
|
307
|
+
end
|
308
|
+
return result.first if result.size == 1
|
309
|
+
result
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# def storage_default(keys_and_defaults)
|
316
|
+
# @frivol_defaults ||= {}
|
317
|
+
# @frivol_defaults.merge keys_and_defaults
|
318
|
+
# end
|
199
319
|
end
|
200
320
|
|
201
321
|
def self.included(host) #:nodoc:
|
data/test/fake_redis.rb
CHANGED
data/test/test_frivol.rb
CHANGED
@@ -2,12 +2,12 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestFrivol < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
#fake_redis # Comment out this line to test against a real live Redis
|
6
|
-
Frivol::Config.redis_config = {} # This will connect to a default Redis setup, otherwise set to { :host => "localhost", :port => 6379 }, for example
|
5
|
+
# fake_redis # Comment out this line to test against a real live Redis
|
6
|
+
Frivol::Config.redis_config = { :thread_safe => true } # This will connect to a default Redis setup, otherwise set to { :host => "localhost", :port => 6379 }, for example
|
7
7
|
end
|
8
8
|
|
9
9
|
def teardown
|
10
|
-
Frivol::Config.redis.
|
10
|
+
Frivol::Config.redis.flushdb
|
11
11
|
end
|
12
12
|
|
13
13
|
should "have a default storage key made up of the class name and id" do
|
@@ -86,7 +86,7 @@ class TestFrivol < Test::Unit::TestCase
|
|
86
86
|
|
87
87
|
should "be able to override the key method" do
|
88
88
|
class OverrideKeyTestClass < TestClass
|
89
|
-
def storage_key
|
89
|
+
def storage_key(bucket = nil)
|
90
90
|
"my_storage"
|
91
91
|
end
|
92
92
|
end
|
@@ -130,10 +130,21 @@ class TestFrivol < Test::Unit::TestCase
|
|
130
130
|
t.save
|
131
131
|
t.expire_storage 0.5
|
132
132
|
sleep 1
|
133
|
-
t = TestClass.new # Get a fresh instance so that the @
|
133
|
+
t = TestClass.new # Get a fresh instance so that the @frivol_data is empty
|
134
134
|
assert_equal "default", t.load
|
135
135
|
end
|
136
136
|
|
137
|
+
should "use default expiry set on the class" do
|
138
|
+
class ExpiryTestClass < TestClass
|
139
|
+
storage_expires_in 0.5
|
140
|
+
end
|
141
|
+
t = ExpiryTestClass.new
|
142
|
+
t.save
|
143
|
+
sleep 1
|
144
|
+
t = TestClass.new # Get a fresh instance so that the @frivol_data is empty
|
145
|
+
assert_equal "default", t.load
|
146
|
+
end
|
147
|
+
|
137
148
|
should "be able to include in other classes with storage expiry" do
|
138
149
|
class BlankTestClass
|
139
150
|
end
|
@@ -156,4 +167,125 @@ class TestFrivol < Test::Unit::TestCase
|
|
156
167
|
t.delete_storage
|
157
168
|
assert_equal "default", t.load
|
158
169
|
end
|
170
|
+
|
171
|
+
should "be able to create and use buckets" do
|
172
|
+
class SimpleBucketTestClass < TestClass
|
173
|
+
storage_bucket :blue
|
174
|
+
end
|
175
|
+
t = SimpleBucketTestClass.new
|
176
|
+
assert t.respond_to?(:store_blue)
|
177
|
+
assert t.respond_to?(:retrieve_blue)
|
178
|
+
end
|
179
|
+
|
180
|
+
should "store different values in different buckets" do
|
181
|
+
class StorageBucketTestClass < TestClass
|
182
|
+
storage_bucket :blue
|
183
|
+
|
184
|
+
def save_blue
|
185
|
+
store_blue :value => "blue value"
|
186
|
+
end
|
187
|
+
|
188
|
+
def load_blue
|
189
|
+
retrieve_blue :value => "blue default"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
t = StorageBucketTestClass.new
|
193
|
+
t.save
|
194
|
+
t.save_blue
|
195
|
+
assert_equal "value", t.load
|
196
|
+
assert_equal "blue value", t.load_blue
|
197
|
+
end
|
198
|
+
|
199
|
+
should "have different expiry times for different buckets" do
|
200
|
+
class ExpireBucketsTestClass < TestClass
|
201
|
+
storage_bucket :blue, :expires_in => 0.5
|
202
|
+
storage_expires_in 2
|
203
|
+
end
|
204
|
+
t = ExpireBucketsTestClass.new
|
205
|
+
assert_equal 0.5, ExpireBucketsTestClass.storage_expiry(:blue)
|
206
|
+
assert_equal 2, ExpireBucketsTestClass.storage_expiry
|
207
|
+
end
|
208
|
+
|
209
|
+
should "expire data in buckets" do
|
210
|
+
class ExpireBucketsTestClass < TestClass
|
211
|
+
storage_bucket :blue, :expires_in => 0.5
|
212
|
+
storage_expires_in 2
|
213
|
+
|
214
|
+
def save_blue
|
215
|
+
store_blue :value => "blue value"
|
216
|
+
end
|
217
|
+
|
218
|
+
def load_blue
|
219
|
+
retrieve_blue :value => "blue default"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
t = ExpireBucketsTestClass.new
|
223
|
+
t.save
|
224
|
+
t.save_blue
|
225
|
+
sleep 1
|
226
|
+
t = ExpireBucketsTestClass.new # get a new instance so @frivol_data is empty
|
227
|
+
assert_equal "value", t.load
|
228
|
+
assert_equal "blue default", t.load_blue
|
229
|
+
end
|
230
|
+
|
231
|
+
should "be able to create counter buckets" do
|
232
|
+
class SimpleCounterTestClass < TestClass
|
233
|
+
storage_bucket :blue, :counter => true
|
234
|
+
end
|
235
|
+
t = SimpleCounterTestClass.new
|
236
|
+
assert t.respond_to?(:store_blue)
|
237
|
+
assert t.respond_to?(:retrieve_blue)
|
238
|
+
assert t.respond_to?(:increment_blue)
|
239
|
+
end
|
240
|
+
|
241
|
+
should "store, increment and retrieve integers in a counter" do
|
242
|
+
class IncrCounterTestClass < TestClass
|
243
|
+
storage_bucket :blue, :counter => true
|
244
|
+
|
245
|
+
def save_blue
|
246
|
+
store_blue 10
|
247
|
+
end
|
248
|
+
|
249
|
+
def load_blue
|
250
|
+
retrieve_blue 0
|
251
|
+
end
|
252
|
+
end
|
253
|
+
t = IncrCounterTestClass.new
|
254
|
+
assert_equal 0, t.load_blue
|
255
|
+
t.save_blue
|
256
|
+
assert_equal 10, t.load_blue
|
257
|
+
assert_equal 11, t.increment_blue
|
258
|
+
assert_equal 11, t.load_blue
|
259
|
+
end
|
260
|
+
|
261
|
+
should "have thread safe counters" do
|
262
|
+
class ThreadCounterTestClass < TestClass
|
263
|
+
storage_bucket :blue, :counter => true
|
264
|
+
|
265
|
+
def save_blue
|
266
|
+
store_blue 10
|
267
|
+
end
|
268
|
+
|
269
|
+
def load_blue
|
270
|
+
retrieve_blue 0
|
271
|
+
end
|
272
|
+
end
|
273
|
+
t = ThreadCounterTestClass.new
|
274
|
+
t.save_blue
|
275
|
+
assert_equal 10, t.load_blue
|
276
|
+
|
277
|
+
threads = []
|
278
|
+
100.times do
|
279
|
+
threads << Thread.new do
|
280
|
+
10.times do
|
281
|
+
temp = ThreadCounterTestClass.new
|
282
|
+
temp.increment_blue
|
283
|
+
sleep(rand(10) / 100.0)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
threads.each { |a| a.join }
|
288
|
+
|
289
|
+
assert_equal 1010, t.load_blue
|
290
|
+
end
|
159
291
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frivol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 5
|
10
|
+
version: 0.1.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marc Heiligers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-15 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -42,12 +42,12 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 27
|
46
46
|
segments:
|
47
|
-
- 0
|
48
|
-
- 1
|
49
47
|
- 2
|
50
|
-
|
48
|
+
- 0
|
49
|
+
- 10
|
50
|
+
version: 2.0.10
|
51
51
|
type: :runtime
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
@@ -87,13 +87,18 @@ files:
|
|
87
87
|
- doc/classes/Frivol.src/M000004.html
|
88
88
|
- doc/classes/Frivol.src/M000005.html
|
89
89
|
- doc/classes/Frivol.src/M000006.html
|
90
|
+
- doc/classes/Frivol.src/M000007.html
|
90
91
|
- doc/classes/Frivol/ClassMethods.html
|
91
92
|
- doc/classes/Frivol/ClassMethods.src/M000007.html
|
92
93
|
- doc/classes/Frivol/ClassMethods.src/M000008.html
|
94
|
+
- doc/classes/Frivol/ClassMethods.src/M000009.html
|
95
|
+
- doc/classes/Frivol/ClassMethods.src/M000010.html
|
93
96
|
- doc/classes/Frivol/Config.html
|
94
97
|
- doc/classes/Frivol/Config.src/M000009.html
|
95
98
|
- doc/classes/Frivol/Config.src/M000010.html
|
96
99
|
- doc/classes/Frivol/Config.src/M000011.html
|
100
|
+
- doc/classes/Frivol/Config.src/M000012.html
|
101
|
+
- doc/classes/Frivol/Config.src/M000013.html
|
97
102
|
- doc/classes/Time.html
|
98
103
|
- doc/classes/Time.src/M000001.html
|
99
104
|
- doc/classes/Time.src/M000002.html
|