familia 0.7.1 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9473b7b95d58032b285d3239087e0152918c0dea1e8c6d3345a02b636ea0b6e3
4
+ data.tar.gz: 44eb92935529e962b9284954849bc8c12667636bc5379f32de57c7d6060b0ffa
5
+ SHA512:
6
+ metadata.gz: ac52ed32ea22521c2400dab6b9b2d195561049cc4ae652868706636ec74c6c7475e7c0bd909c32d7cc468b97bd62a1e4286f827f636d785810141b4a29ad9dd3
7
+ data.tar.gz: b3d35682e4d316f58724ebae3f5731036065c3491ec1e0b661cb24c1bbceb288371290ea8d9eedb2f4b7a9adc7f0c26fb6d31c8e78dc8d45b044aa5156623971
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ .bundle
3
+ .byebug*
4
+ .history
5
+ .devcontainer
6
+ .vscode
7
+ *.env
8
+ *.log
9
+ *.md
10
+ *.txt
11
+ !LICENSE.txt
12
+ .ruby-version
13
+ appendonlydir
14
+ etc/config
15
+ log
16
+ tmp
17
+ vendor
18
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '>= 2.6.8'
4
+
5
+ gem 'redis', '~> 4.8'
6
+ gem 'uri-redis'
7
+ gem 'gibbler'
8
+ gem 'storable'
9
+ gem 'multi_json'
10
+
11
+ group :development, :test do
12
+ gem 'tryouts', '~> 2.2'
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ attic (1.0.0)
5
+ rake (~> 13.0.6)
6
+ drydock (0.6.9)
7
+ gibbler (1.0.0)
8
+ attic (~> 1.0)
9
+ rake (~> 13.0)
10
+ multi_json (1.15.0)
11
+ rake (13.0.6)
12
+ redis (4.8.1)
13
+ storable (0.10.0)
14
+ sysinfo (0.10.0)
15
+ drydock (< 1.0)
16
+ storable (~> 0.10)
17
+ tryouts (2.2.0)
18
+ sysinfo (~> 0.10)
19
+ uri-redis (0.4.2)
20
+
21
+ PLATFORMS
22
+ arm64-darwin-22
23
+
24
+ DEPENDENCIES
25
+ gibbler
26
+ multi_json
27
+ redis (~> 4.8)
28
+ storable
29
+ tryouts (~> 2.2)
30
+ uri-redis
31
+
32
+ RUBY VERSION
33
+ ruby 2.6.8p205
34
+
35
+ BUNDLED WITH
36
+ 2.4.12
@@ -1,29 +1,24 @@
1
- # Familia - 0.7 BETA
1
+ # Familia - 0.9 (2024-04-04)
2
2
 
3
3
  **Organize and store ruby objects in Redis**
4
4
 
5
5
 
6
6
  ## Basic Example
7
7
 
8
- class Bone < Storable
8
+ ```ruby
9
+ class Flower < Storable
9
10
  include Familia
10
11
  index [:token, :name]
11
- field :token
12
- field :name
12
+ field :token
13
+ field :name
13
14
  list :owners
14
15
  set :tags
15
16
  zset :metrics
16
17
  hash :props
17
18
  string :value, :default => "GREAT!"
18
19
  end
19
-
20
-
21
- ## More Information
22
-
23
- * [Codes](http://github.com/delano/familia)
24
- * [RDocs](http://delano.github.com/familia)
20
+ ```
25
21
 
22
+ ## More Information
26
23
 
27
- ## Credits
28
-
29
- * [Delano Mandelbaum](http://goldensword.ca)
24
+ * [Codes](https://github.com/delano/familia)
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
- ---
1
+ ---
2
2
  :MAJOR: 0
3
- :MINOR: 7
3
+ :MINOR: 9
4
4
  :PATCH: 1
data/familia.gemspec CHANGED
@@ -1,74 +1,23 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
1
  Gem::Specification.new do |s|
7
- s.name = %q{familia}
8
- s.version = "0.7.1"
2
+ s.name = "familia"
3
+ s.version = "0.9.1"
4
+ s.summary = "Organize and store ruby objects in Redis"
5
+ s.description = "Familia: #{s.summary}"
6
+ s.authors = ["Delano Mandelbaum"]
7
+ s.email = "delano@solutious.com"
8
+ s.homepage = "https://github.com/delano/familia"
9
+ s.license = "MIT"
9
10
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Delano Mandelbaum"]
12
- s.date = %q{2011-04-11}
13
- s.description = %q{Organize and store ruby objects in Redis}
14
- s.email = %q{delano@solutious.com}
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- "CHANGES.txt",
21
- "LICENSE.txt",
22
- "README.rdoc",
23
- "Rakefile",
24
- "VERSION.yml",
25
- "familia.gemspec",
26
- "lib/familia.rb",
27
- "lib/familia/core_ext.rb",
28
- "lib/familia/helpers.rb",
29
- "lib/familia/object.rb",
30
- "lib/familia/redisobject.rb",
31
- "lib/familia/test_helpers.rb",
32
- "lib/familia/tools.rb",
33
- "try/00_familia.rb",
34
- "try/10_familia_try.rb",
35
- "try/20_redis_object_try.rb",
36
- "try/21_redis_object_zset_try.rb",
37
- "try/22_redis_object_set_try.rb",
38
- "try/23_redis_object_list_try.rb",
39
- "try/24_redis_object_string_try.rb",
40
- "try/25_redis_object_hash_try.rb",
41
- "try/30_familia_object_try.rb"
42
- ]
43
- s.homepage = %q{http://github.com/delano/familia}
44
- s.rdoc_options = ["--charset=UTF-8"]
11
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
12
+ s.bindir = "exe"
13
+ s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
45
14
  s.require_paths = ["lib"]
46
- s.rubyforge_project = %q{familia}
47
- s.rubygems_version = %q{1.5.2}
48
- s.summary = %q{Organize and store ruby objects in Redis}
49
15
 
50
- if s.respond_to? :specification_version then
51
- s.specification_version = 3
16
+ s.required_ruby_version = Gem::Requirement.new(">= 2.6.8")
52
17
 
53
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
- s.add_runtime_dependency(%q<redis>, [">= 2.1.0"])
55
- s.add_runtime_dependency(%q<uri-redis>, [">= 0.4.2"])
56
- s.add_runtime_dependency(%q<gibbler>, [">= 0.8.6"])
57
- s.add_runtime_dependency(%q<storable>, [">= 0.8.6"])
58
- s.add_runtime_dependency(%q<multi_json>, [">= 0.0.5"])
59
- else
60
- s.add_dependency(%q<redis>, [">= 2.1.0"])
61
- s.add_dependency(%q<uri-redis>, [">= 0.4.2"])
62
- s.add_dependency(%q<gibbler>, [">= 0.8.6"])
63
- s.add_dependency(%q<storable>, [">= 0.8.6"])
64
- s.add_dependency(%q<multi_json>, [">= 0.0.5"])
65
- end
66
- else
67
- s.add_dependency(%q<redis>, [">= 2.1.0"])
68
- s.add_dependency(%q<uri-redis>, [">= 0.4.2"])
69
- s.add_dependency(%q<gibbler>, [">= 0.8.6"])
70
- s.add_dependency(%q<storable>, [">= 0.8.6"])
71
- s.add_dependency(%q<multi_json>, [">= 0.0.5"])
72
- end
18
+ s.add_dependency "redis", "~> 5.1.0"
19
+ s.add_dependency "uri-redis", ">= 0.4.2"
20
+ s.add_dependency "gibbler", "~> 1.0.0"
21
+ s.add_dependency "storable", "~> 0.10.0"
22
+ s.add_dependency "multi_json", "~> 1.15"
73
23
  end
74
-
@@ -2,12 +2,12 @@ require 'ostruct'
2
2
 
3
3
  module Familia
4
4
  require 'familia/redisobject'
5
-
5
+
6
6
  # Auto-extended into a class that includes Familia
7
7
  module ClassMethods
8
-
8
+
9
9
  Familia::RedisObject.registration.each_pair do |kind, klass|
10
- # e.g.
10
+ # e.g.
11
11
  #
12
12
  # list(name, klass, opts)
13
13
  # list?(name)
@@ -22,12 +22,12 @@ module Familia
22
22
  obj = redis_objects[name.to_s.to_sym]
23
23
  !obj.nil? && klass == obj.klass
24
24
  end
25
- define_method :"#{kind}s" do
25
+ define_method :"#{kind}s" do
26
26
  names = redis_objects_order.select { |name| send(:"#{kind}?", name) }
27
27
  names.collect! { |name| redis_objects[name] }
28
28
  names
29
29
  end
30
- # e.g.
30
+ # e.g.
31
31
  #
32
32
  # class_list(name, klass, opts)
33
33
  # class_list?(name)
@@ -41,11 +41,11 @@ module Familia
41
41
  obj = class_redis_objects[name.to_s.to_sym]
42
42
  !obj.nil? && klass == obj.klass
43
43
  end
44
- define_method :"class_#{kind}s" do
44
+ define_method :"class_#{kind}s" do
45
45
  names = class_redis_objects_order.select { |name| ret = send(:"class_#{kind}?", name) }
46
46
  # TODO: This returns instances of the RedisObject class which
47
47
  # also contain the options. This is different from the instance
48
- # RedisObjects defined above which returns the OpenStruct of name, klass, and opts.
48
+ # RedisObjects defined above which returns the OpenStruct of name, klass, and opts.
49
49
  #names.collect! { |name| self.send name }
50
50
  # OR NOT:
51
51
  names.collect! { |name| class_redis_objects[name] }
@@ -69,9 +69,9 @@ module Familia
69
69
  obj.class_zset :instances, :class => obj, :reference => true
70
70
  Familia.classes << obj
71
71
  end
72
-
72
+
73
73
  # Creates an instance method called +name+ that
74
- # returns an instance of the RedisObject +klass+
74
+ # returns an instance of the RedisObject +klass+
75
75
  def install_redis_object name, klass, opts
76
76
  raise ArgumentError, "Name is blank" if name.to_s.empty?
77
77
  name = name.to_s.to_sym
@@ -90,34 +90,34 @@ module Familia
90
90
  end
91
91
  redis_objects[name]
92
92
  end
93
-
93
+
94
94
  def qstamp quantum=nil, pattern=nil, now=Familia.now
95
95
  quantum ||= ttl || 10.minutes
96
96
  pattern ||= '%H%M'
97
97
  rounded = now - (now % quantum)
98
98
  Time.at(rounded).utc.strftime(pattern)
99
99
  end
100
-
100
+
101
101
  # Creates a class method called +name+ that
102
- # returns an instance of the RedisObject +klass+
102
+ # returns an instance of the RedisObject +klass+
103
103
  def install_class_redis_object name, klass, opts
104
104
  raise ArgumentError, "Name is blank" if name.to_s.empty?
105
105
  name = name.to_s.to_sym
106
106
  opts = opts.nil? ? {} : opts.clone
107
107
  opts[:parent] = self unless opts.has_key?(:parent)
108
- # TODO: investigate using metaclass.redis_objects
108
+ # TODO: investigate using attic.redis_objects
109
109
  class_redis_objects_order << name
110
110
  class_redis_objects[name] = OpenStruct.new
111
111
  class_redis_objects[name].name = name
112
112
  class_redis_objects[name].klass = klass
113
- class_redis_objects[name].opts = opts
113
+ class_redis_objects[name].opts = opts
114
114
  # An accessor method created in the metclass will
115
- # access the instance variables for this class.
116
- metaclass.send :attr_reader, name
117
- metaclass.send :define_method, "#{name}=" do |v|
115
+ # access the instance variables for this class.
116
+ attic.send :attr_reader, name
117
+ attic.send :define_method, "#{name}=" do |v|
118
118
  send(name).replace v
119
119
  end
120
- metaclass.send :define_method, "#{name}?" do
120
+ attic.send :define_method, "#{name}?" do
121
121
  !send(name).empty?
122
122
  end
123
123
  redis_object = klass.new name, opts
@@ -125,7 +125,7 @@ module Familia
125
125
  self.instance_variable_set("@#{name}", redis_object)
126
126
  class_redis_objects[name]
127
127
  end
128
-
128
+
129
129
  def from_redisdump dump
130
130
  dump # todo
131
131
  end
@@ -146,9 +146,9 @@ module Familia
146
146
  def port=(port) @port = port end
147
147
  def uri=(uri)
148
148
  uri = URI.parse uri if String === uri
149
- @uri = uri
149
+ @uri = uri
150
150
  end
151
- def uri(uri=nil)
151
+ def uri(uri=nil)
152
152
  self.uri = uri if !uri.to_s.empty?
153
153
  @uri ||= (parent ? parent.uri : Familia.uri)
154
154
  @uri.db = @db if @db && @uri.db.to_s != @db.to_s
@@ -166,7 +166,7 @@ module Familia
166
166
  end
167
167
  def all(suffix=:object)
168
168
  # objects that could not be parsed will be nil
169
- keys(suffix).collect { |k| from_key(k) }.compact
169
+ keys(suffix).collect { |k| from_key(k) }.compact
170
170
  end
171
171
  def any?(filter='*')
172
172
  size(filter) > 0
@@ -174,7 +174,7 @@ module Familia
174
174
  def size(filter='*')
175
175
  self.redis.keys(rediskey(filter)).compact.size
176
176
  end
177
- def suffix(a=nil, &blk)
177
+ def suffix(a=nil, &blk)
178
178
  @suffix = a || blk if a || !blk.nil?
179
179
  val = @suffix || Familia.default_suffix
180
180
  val
@@ -184,7 +184,7 @@ module Familia
184
184
  # TODO: grab db, ttl, uri from parent
185
185
  #def parent=(a) @parent = a end
186
186
  #def parent(a=nil) @parent = a if a; @parent end
187
- def index(i=nil, &blk)
187
+ def index(i=nil, &blk)
188
188
  @index = i || blk if i || !blk.nil?
189
189
  @index ||= Familia.index
190
190
  @index
@@ -230,9 +230,9 @@ module Familia
230
230
  Familia.trace :MULTIGET, self.redis, "#{ids.size}: #{ids}", caller if Familia.debug?
231
231
  ids = self.redis.mget *ids
232
232
  end
233
-
233
+
234
234
  # Returns an instance based on +idx+ otherwise it
235
- # creates and saves a new instance base on +idx+.
235
+ # creates and saves a new instance base on +idx+.
236
236
  # See from_index
237
237
  def load_or_create idx
238
238
  return from_redis(idx) if exists?(idx)
@@ -240,17 +240,17 @@ module Familia
240
240
  obj.save
241
241
  obj
242
242
  end
243
- # Note +idx+ needs to be an appropriate index for
243
+ # Note +idx+ needs to be an appropriate index for
244
244
  # the given class. If the index is multi-value it
245
245
  # must be passed as an Array in the proper order.
246
246
  # Does not call save.
247
247
  def from_index idx
248
- obj = new
248
+ obj = new
249
249
  obj.index = idx
250
250
  obj
251
251
  end
252
252
  def from_key objkey
253
- raise ArgumentError, "Empty key" if objkey.to_s.empty?
253
+ raise ArgumentError, "Empty key" if objkey.to_s.empty?
254
254
  Familia.trace :LOAD, Familia.redis(self.uri), objkey, caller if Familia.debug?
255
255
  obj = Familia::String.new objkey, :class => self
256
256
  obj.value
@@ -293,18 +293,18 @@ module Familia
293
293
  case list.size
294
294
  when 0
295
295
  nil
296
- when 1
296
+ when 1
297
297
  matches = list.first.match(/\A#{Familia.rediskey(prefix)}\:(.+?)\:#{suffix}/) || []
298
298
  matches[1]
299
299
  else
300
- raise Familia::NonUniqueKey, "Short key returned more than 1 match"
300
+ raise Familia::NonUniqueKey, "Short key returned more than 1 match"
301
301
  end
302
302
  end
303
303
  end
304
304
 
305
-
305
+
306
306
  module InstanceMethods
307
-
307
+
308
308
  # A default initialize method. This will be replaced
309
309
  # if a class defines its own initialize method after
310
310
  # including Familia. In that case, the replacement
@@ -313,15 +313,15 @@ module Familia
313
313
  initialize_redis_objects
314
314
  init *args if respond_to? :init
315
315
  end
316
-
316
+
317
317
  # This needs to be called in the initialize method of
318
- # any class that includes Familia.
318
+ # any class that includes Familia.
319
319
  def initialize_redis_objects
320
320
  # Generate instances of each RedisObject. These need to be
321
321
  # unique for each instance of this class so they can refer
322
322
  # to the index of this specific instance.
323
323
  #
324
- # i.e.
324
+ # i.e.
325
325
  # familia_object.rediskey == v1:bone:INDEXVALUE:object
326
326
  # familia_object.redis_object.rediskey == v1:bone:INDEXVALUE:name
327
327
  #
@@ -335,19 +335,19 @@ module Familia
335
335
  self.instance_variable_set "@#{name}", redis_object
336
336
  end
337
337
  end
338
-
338
+
339
339
  def qstamp quantum=nil, pattern=nil, now=Familia.now
340
340
  self.class.qstamp ttl, pattern, now
341
341
  end
342
-
343
- def from_redis
342
+
343
+ def from_redis
344
344
  self.class.from_redis self.index
345
345
  end
346
-
346
+
347
347
  def redis
348
348
  self.class.redis
349
349
  end
350
-
350
+
351
351
  def redisinfo
352
352
  info = {
353
353
  :uri => self.class.uri,
@@ -359,32 +359,32 @@ module Familia
359
359
  end
360
360
  def exists?
361
361
  Familia.redis(self.class.uri).exists rediskey
362
- end
363
-
362
+ end
363
+
364
364
  #def rediskeys
365
365
  # self.class.redis_objects.each do |redis_object_definition|
366
- #
366
+ #
367
367
  # end
368
368
  #end
369
-
369
+
370
370
  def allkeys
371
371
  # TODO: Use redis_objects instead
372
372
  keynames = []
373
- self.class.suffixes.each do |sfx|
373
+ self.class.suffixes.each do |sfx|
374
374
  keynames << rediskey(sfx)
375
375
  end
376
376
  keynames
377
377
  end
378
378
  # +suffix+ is the value to be used at the end of the redis key
379
379
  # + ignored+ is literally ignored. It's around to maintain
380
- # consistency with the class version of this method.
380
+ # consistency with the class version of this method.
381
381
  # (RedisObject#rediskey may call against a class or instance).
382
382
  def rediskey(suffix=nil, ignored=nil)
383
383
  Familia.info "[#{self.class}] something was ignored" unless ignored.nil?
384
384
  raise Familia::NoIndex, self.class if index.to_s.empty?
385
385
  if suffix.nil?
386
- suffix = self.class.suffix.kind_of?(Proc) ?
387
- self.class.suffix.call(self) :
386
+ suffix = self.class.suffix.kind_of?(Proc) ?
387
+ self.class.suffix.call(self) :
388
388
  self.class.suffix
389
389
  end
390
390
  self.class.rediskey self.index, suffix
@@ -405,7 +405,7 @@ module Familia
405
405
  end
406
406
  ret == "OK" || ret == true || ret == 1
407
407
  end
408
- def savenx
408
+ def savenx
409
409
  save :setnx
410
410
  end
411
411
  def update! hsh=nil
@@ -416,10 +416,10 @@ module Familia
416
416
  ret = from_redis
417
417
  hsh = ret.to_hash if ret
418
418
  end
419
- hsh.keys.each { |field|
419
+ hsh.keys.each { |field|
420
420
  v = hsh[field.to_s] || hsh[field.to_s.to_sym]
421
421
  next if v.nil?
422
- self.send(:"#{field}=", v)
422
+ self.send(:"#{field}=", v)
423
423
  updated = true
424
424
  }
425
425
  updated
@@ -437,7 +437,7 @@ module Familia
437
437
  when Proc
438
438
  self.class.index.call(self)
439
439
  when Array
440
- parts = self.class.index.collect { |meth|
440
+ parts = self.class.index.collect { |meth|
441
441
  unless self.respond_to? meth
442
442
  raise NoIndex, "No such method: `#{meth}' for #{self.class}"
443
443
  end
@@ -469,11 +469,11 @@ module Familia
469
469
  unless Array === v && v.size == self.class.index.size
470
470
  raise ArgumentError, "Index mismatch (#{v.size} for #{self.class.index.size})"
471
471
  end
472
- parts = self.class.index.each_with_index { |meth,idx|
472
+ parts = self.class.index.each_with_index { |meth,idx|
473
473
  unless self.respond_to? "#{meth}="
474
474
  raise NoIndex, "No such method: `#{meth}=' for #{self.class}"
475
475
  end
476
- self.send("#{meth}=", v[idx])
476
+ self.send("#{meth}=", v[idx])
477
477
  }
478
478
  when Symbol, String
479
479
  if self.class.redis_object?(self.class.index.to_sym)
@@ -487,7 +487,7 @@ module Familia
487
487
  else
488
488
  raise Familia::NoIndex, self
489
489
  end
490
-
490
+
491
491
  end
492
492
  def expire(ttl=nil)
493
493
  ttl ||= self.class.ttl
@@ -526,8 +526,8 @@ module Familia
526
526
  len += 1
527
527
  end
528
528
  end
529
- @id.shorten(len)
529
+ @id.shorten(len)
530
530
  end
531
531
  end
532
-
533
- end
532
+
533
+ end