redis_object 0.5.0

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.
Files changed (49) hide show
  1. data/.coveralls.yml +1 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +8 -0
  5. data/README.markdown +179 -0
  6. data/Rakefile +10 -0
  7. data/lib/redis_object.rb +47 -0
  8. data/lib/redis_object/base.rb +408 -0
  9. data/lib/redis_object/collection.rb +388 -0
  10. data/lib/redis_object/defaults.rb +42 -0
  11. data/lib/redis_object/experimental/history.rb +49 -0
  12. data/lib/redis_object/ext/benchmark.rb +34 -0
  13. data/lib/redis_object/ext/cleaner.rb +14 -0
  14. data/lib/redis_object/ext/filters.rb +68 -0
  15. data/lib/redis_object/ext/script_cache.rb +92 -0
  16. data/lib/redis_object/ext/shardable.rb +18 -0
  17. data/lib/redis_object/ext/triggers.rb +101 -0
  18. data/lib/redis_object/ext/view_caching.rb +258 -0
  19. data/lib/redis_object/ext/views.rb +102 -0
  20. data/lib/redis_object/external_index.rb +25 -0
  21. data/lib/redis_object/indices.rb +97 -0
  22. data/lib/redis_object/inheritance_tracking.rb +23 -0
  23. data/lib/redis_object/keys.rb +37 -0
  24. data/lib/redis_object/storage.rb +93 -0
  25. data/lib/redis_object/storage/adapter.rb +46 -0
  26. data/lib/redis_object/storage/aws.rb +71 -0
  27. data/lib/redis_object/storage/mysql.rb +47 -0
  28. data/lib/redis_object/storage/redis.rb +119 -0
  29. data/lib/redis_object/timestamps.rb +74 -0
  30. data/lib/redis_object/tpl.rb +17 -0
  31. data/lib/redis_object/types.rb +276 -0
  32. data/lib/redis_object/validation.rb +89 -0
  33. data/lib/redis_object/version.rb +5 -0
  34. data/redis_object.gemspec +26 -0
  35. data/spec/adapter_spec.rb +43 -0
  36. data/spec/base_spec.rb +90 -0
  37. data/spec/benchmark_spec.rb +46 -0
  38. data/spec/collections_spec.rb +144 -0
  39. data/spec/defaults_spec.rb +56 -0
  40. data/spec/filters_spec.rb +29 -0
  41. data/spec/indices_spec.rb +45 -0
  42. data/spec/rename_class_spec.rb +96 -0
  43. data/spec/spec_helper.rb +38 -0
  44. data/spec/timestamp_spec.rb +28 -0
  45. data/spec/trigger_spec.rb +51 -0
  46. data/spec/types_spec.rb +103 -0
  47. data/spec/view_caching_spec.rb +130 -0
  48. data/spec/views_spec.rb +72 -0
  49. metadata +172 -0
@@ -0,0 +1,89 @@
1
+ module Seabright
2
+
3
+ module Validation
4
+
5
+ def valid?
6
+ ret = true
7
+ errors = []
8
+ self.class.required_fields.each do |k|
9
+ unless is_valid?(k)
10
+ errors.push "#{k} is not valid and is needed to process."
11
+ ret = false
12
+ end
13
+ end
14
+ self.class.required_collections.each do |k|
15
+ unless has_collection?(k)
16
+ errors.push "Need a #{k} collection to proceed."
17
+ ret = false
18
+ end
19
+ end
20
+ ret
21
+ end
22
+
23
+ def is_set?(k)
24
+ store.hexists(hkey,k)
25
+ end
26
+
27
+ def is_valid?(k)
28
+ return false unless is_set?(k)
29
+ return true unless validations[k]
30
+ if val = get(k)
31
+ case validations[k].class
32
+ when Regexp
33
+ return false unless validations[k].match(val)
34
+ when Array
35
+ return false unless validations[k].include?(val)
36
+ else
37
+ if validations[k].class == Class
38
+ return false unless val.class == validations[k]
39
+ end
40
+ end
41
+ end
42
+ true
43
+ end
44
+
45
+ def validations
46
+ @validations ||= self.class.validations
47
+ end
48
+
49
+ module ClassMethods
50
+
51
+ def require_field(*args)
52
+ args.each do |k|
53
+ required_fields.push k.to_sym
54
+ end
55
+ end
56
+ alias_method :require_fields, :require_field
57
+
58
+ def require_collection(*args)
59
+ args.each do |k|
60
+ required_collections.push k.to_sym
61
+ end
62
+ end
63
+ alias_method :require_collections, :require_collection
64
+
65
+ def required_collections
66
+ @required_cols ||= []
67
+ end
68
+
69
+ def required_fields
70
+ @required ||= []
71
+ end
72
+
73
+ def validate(k,rl)
74
+ validations[k] = rl
75
+ end
76
+
77
+ def validations
78
+ @validations ||= {}
79
+ end
80
+
81
+ end
82
+
83
+ def self.included(base)
84
+ base.extend(ClassMethods)
85
+ end
86
+
87
+ end
88
+
89
+ end
@@ -0,0 +1,5 @@
1
+ module Seabright
2
+ class RedisObject
3
+ VERSION = "0.5.0"
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "redis_object/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redis_object"
7
+ s.version = Seabright::RedisObject::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["John Bragg"]
10
+ s.email = ["john@seabrightstudios.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Maps arbitrary objects to a Redis store with indices and smart retrieval and storage mechanisms.}
13
+ s.description = %q{}
14
+
15
+ s.rubyforge_project = "redis_object"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.required_ruby_version = '>= 1.9.2'
22
+ s.add_dependency "utf8_utils"
23
+ s.add_dependency "redis"
24
+ s.add_dependency "yajl-ruby"
25
+ s.add_dependency "activesupport"
26
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module ObjectTests
4
+ class User < RedisObject
5
+ use_store :global
6
+ end
7
+ class Thingy < RedisObject
8
+
9
+ end
10
+ class Doodad < RedisObject
11
+
12
+ end
13
+ end
14
+
15
+ describe RedisObject do
16
+
17
+ it "can reconnect to redis" do
18
+ RedisObject.reconnect!
19
+ RedisObject.store.reconnect!
20
+ end
21
+
22
+ it "can dump to a file" do
23
+ obj = ObjectTests::User.create("test")
24
+ RedisObject.dump_stores_to_files("/tmp")
25
+ RedisObject.store.flushdb
26
+ end
27
+
28
+ it "can restore from a file" do
29
+ RedisObject.restore_stores_from_files("/tmp")
30
+ ObjectTests::User.find("test").should be_a(ObjectTests::User)
31
+ end
32
+
33
+ it "can get all stores" do
34
+ RedisObject.stores.count.should eq(1)
35
+ end
36
+
37
+ it "can reset stores" do
38
+ RedisObject.stores.each do |(name,store)|
39
+ store.reset
40
+ end
41
+ end
42
+
43
+ end
data/spec/base_spec.rb ADDED
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module ObjectTests
4
+ class User < RedisObject
5
+ use_store :global
6
+ end
7
+ class Thingy < RedisObject
8
+
9
+ end
10
+ class Doodad < RedisObject
11
+
12
+ end
13
+ end
14
+
15
+ describe RedisObject do
16
+
17
+ it "can be created" do
18
+ obj = ObjectTests::User.new
19
+ end
20
+
21
+ it "can be created with an id" do
22
+ obj = ObjectTests::User.new("test")
23
+ obj.save
24
+ end
25
+
26
+ it "can create an id" do
27
+ obj = ObjectTests::User.new("test")
28
+ obj.new_id
29
+ end
30
+
31
+ it "can reserve an id" do
32
+ obj = ObjectTests::User.new("test")
33
+ obj.reserve("test")
34
+ end
35
+
36
+ it "should be found by id" do
37
+ obj = ObjectTests::User.find("test")
38
+ obj.should_not be_nil
39
+ end
40
+
41
+ it "can recollect objects" do
42
+ ObjectTests::User.recollect!
43
+ end
44
+
45
+ it "get get the first object (random)" do
46
+ obj = ObjectTests::User.first
47
+ obj.should be_a(ObjectTests::User)
48
+ end
49
+
50
+ it "should save stuff" do
51
+ obj = ObjectTests::User.find("test")
52
+ obj.stuff = "yay!"
53
+ obj[:stuff].should eq("yay!")
54
+ obj[:stuff] = "yayyay!"
55
+ obj.stuff.should eq("yayyay!")
56
+ obj.stuff = "yay!"
57
+ obj.stuff.should eq("yay!")
58
+ end
59
+
60
+ it "should retrieve stuff" do
61
+ obj = ObjectTests::User.find("test")
62
+ obj.stuff.should eq("yay!")
63
+ end
64
+
65
+ it "can collect other objects" do
66
+ obj = ObjectTests::User.find("test")
67
+ obj2 = ObjectTests::Thingy.new("yay")
68
+ obj << obj2
69
+ obj.should have_collection(:thingies)
70
+ end
71
+
72
+ it "can reference other objects" do
73
+ obj = ObjectTests::User.find("test")
74
+ obj3 = ObjectTests::Doodad.new("woo")
75
+ obj.reference obj3
76
+ obj.should have_collection(:doodads)
77
+ end
78
+
79
+ it "can convert raw to json" do
80
+ obj = ObjectTests::User.find("test")
81
+ obj.to_json.length.should > 0
82
+ end
83
+
84
+ it "should be deletable" do
85
+ obj = ObjectTests::User.find("test")
86
+ obj.delete!
87
+ ObjectTests::User.find("test").should be_nil
88
+ end
89
+
90
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module BenchmarkSpec
4
+
5
+ TestValues = {
6
+ date: Date.today,
7
+ number: 27,
8
+ int: 356192,
9
+ float: 72.362517,
10
+ bool: true,
11
+ # boolean: false,
12
+ # array: [:test1,:test2],
13
+ json: {test1: true, test2: "false"}
14
+ }
15
+
16
+ TestData = TestValues.inject({}){|acc,(k,v)| acc["a_#{k}".to_sym] = v; acc }
17
+
18
+ class BenchmarkedObject < RedisObject
19
+
20
+ TestValues.keys.each do |type|
21
+ send(type.to_sym,"a_#{type}".to_sym)
22
+ end
23
+
24
+ def aggregate
25
+ sleep 0.1
26
+ 42.7
27
+ end
28
+ benchmark :aggregate
29
+
30
+ end
31
+
32
+ describe Seabright::Benchmark do
33
+ before do
34
+ RedisObject.store.flushdb
35
+ end
36
+
37
+ it "benchmarks a call" do
38
+
39
+ obj = BenchmarkedObject.create(TestData)
40
+
41
+ obj.aggregate.should eq(42.7)
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,144 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module CollectionSpec
4
+
5
+ class GrandDad < RedisObject; end
6
+ class Daddy < RedisObject; end
7
+ class Son < RedisObject; end
8
+ class GrandSon < RedisObject; end
9
+
10
+ describe Seabright::Collections do
11
+ before do
12
+
13
+ RedisObject.store.flushdb
14
+ @granddad = GrandDad.create("gramps")
15
+ @dad = Daddy.create("dad")
16
+ @son = Son.create("sun")
17
+ @sonny = Son.create("sonny")
18
+ @grandson = GrandSon.create("baby")
19
+ GrandDad << @dad
20
+ @granddad << @dad
21
+ @granddad << @son
22
+ @dad << @son
23
+ @dad.push @sonny
24
+ @son.reference @grandson
25
+
26
+ end
27
+
28
+ it "can reference other objects" do
29
+
30
+ @granddad.daddies.count.should eq(1)
31
+ @granddad.sons.count.should eq(1)
32
+ @dad.sons.count.should eq(2)
33
+
34
+ end
35
+
36
+ it "should have appropriate collections" do
37
+
38
+ @granddad.has_collection?(:daddies).should eq(true)
39
+ @granddad.has_collection?(:sons).should eq(true)
40
+ @granddad.has_collection?(:grand_sons).should eq(false)
41
+
42
+ end
43
+
44
+ it "should cache collection accessors" do
45
+
46
+ @granddad.daddies.should be_a(Seabright::Collection)
47
+ @granddad.daddy.should be_a(Daddy)
48
+
49
+ end
50
+
51
+ it "should be able to iterate over collected items" do
52
+
53
+ @dad.sons.count.should eq(2)
54
+ @dad.sons.each do |s|
55
+ s.should be_a(Son)
56
+ end
57
+
58
+ end
59
+
60
+ it "can find items in a collection" do
61
+
62
+ @dad = Daddy.find("dad")
63
+ @dad.sons.find(son_id: "sonny").first.should be_a(Son)
64
+
65
+ end
66
+
67
+ it "can get one collection item" do
68
+
69
+ @dad = Daddy.find("dad")
70
+ @dad.son.should be_a(Son)
71
+
72
+ end
73
+
74
+ it "can get one collection item" do
75
+
76
+ @dad = Daddy.find("dad")
77
+ @dad.get(:son).should be_a(Son)
78
+
79
+ end
80
+
81
+ it "can get backreferences of a type" do
82
+
83
+ @son.backreferences(GrandDad).each do |s|
84
+ s.should be_a(GrandDad)
85
+ end
86
+
87
+ end
88
+
89
+ it "can dereference itself" do
90
+
91
+ @dad.dereference_from_backreferences
92
+ GrandDad.find("gramps").daddies.count.should eq(0)
93
+
94
+ end
95
+
96
+ it "can delete items from a collection" do
97
+
98
+ @dad.sons.delete(@sonny)
99
+ @dad.sons.find(son_id: "sonny").first.should be_a(NilClass)
100
+ @dad.sons.count.should eq(1)
101
+
102
+ @dad.delete_child(@son)
103
+ @dad.get(:sons).count.should eq(0)
104
+
105
+ end
106
+
107
+ it "can delete a collection" do
108
+
109
+ @dad.sons.remove!
110
+ @dad.collections.keys.should_not include(:sons)
111
+ @son.remove_collection!(:grand_sons)
112
+ @son.collections.keys.should_not include(:grand_sons)
113
+
114
+ end
115
+
116
+ it "retrieves via index" do
117
+
118
+ 5.times do
119
+ @dad << Son.create
120
+ end
121
+
122
+ # @dad.sons.indexed(:created_at,3,true).count.should eq(3)
123
+
124
+ Son.indexed(:created_at,3,true).count.should eq(3)
125
+
126
+ end
127
+
128
+ it "can collect on classes themselves" do
129
+
130
+ 5.times do
131
+ Daddy << Son.create
132
+ end
133
+
134
+ Daddy.get(:sons).should be_a(Seabright::Collection)
135
+ Daddy.get(:sons).count.should eq(5)
136
+ Daddy.get(:son).should be_a(Son)
137
+ Daddy.delete_child(Daddy.get(:son))
138
+ Daddy.get(:sons).count.should eq(4)
139
+ # Daddy.get(:sons).indexed(:created_at,3,true).count.should eq(3)
140
+
141
+ end
142
+
143
+ end
144
+ end