redis_object 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/.coveralls.yml +1 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +4 -0
  5. data/README.markdown +24 -15
  6. data/Rakefile +8 -0
  7. data/lib/redis_object.rb +11 -1
  8. data/lib/redis_object/base.rb +210 -60
  9. data/lib/redis_object/collection.rb +130 -100
  10. data/lib/redis_object/defaults.rb +21 -8
  11. data/lib/redis_object/{history.rb → experimental/history.rb} +0 -0
  12. data/lib/redis_object/ext/filters.rb +34 -16
  13. data/lib/redis_object/ext/script_cache.rb +92 -0
  14. data/lib/redis_object/ext/shardable.rb +18 -0
  15. data/lib/redis_object/ext/triggers.rb +75 -13
  16. data/lib/redis_object/ext/view_caching.rb +258 -0
  17. data/lib/redis_object/ext/views.rb +102 -0
  18. data/lib/redis_object/indices.rb +44 -39
  19. data/lib/redis_object/inheritance_tracking.rb +23 -0
  20. data/lib/redis_object/keys.rb +4 -4
  21. data/lib/redis_object/storage.rb +30 -1
  22. data/lib/redis_object/storage/adapter.rb +6 -3
  23. data/lib/redis_object/storage/redis.rb +98 -3
  24. data/lib/redis_object/timestamps.rb +42 -21
  25. data/lib/redis_object/types.rb +172 -30
  26. data/lib/redis_object/version.rb +1 -1
  27. data/redis_object.gemspec +1 -0
  28. data/spec/adapter_spec.rb +43 -0
  29. data/spec/base_spec.rb +41 -6
  30. data/spec/benchmark_spec.rb +46 -0
  31. data/spec/collections_spec.rb +144 -0
  32. data/spec/defaults_spec.rb +56 -0
  33. data/spec/filters_spec.rb +29 -0
  34. data/spec/indices_spec.rb +45 -0
  35. data/spec/rename_class_spec.rb +96 -0
  36. data/spec/spec_helper.rb +32 -1
  37. data/spec/timestamp_spec.rb +28 -0
  38. data/spec/trigger_spec.rb +51 -0
  39. data/spec/types_spec.rb +103 -0
  40. data/spec/view_caching_spec.rb +130 -0
  41. data/spec/views_spec.rb +72 -0
  42. metadata +111 -116
  43. data/doc/Object.html +0 -185
  44. data/doc/Seabright.html +0 -181
  45. data/doc/Seabright/Adapter.html +0 -442
  46. data/doc/Seabright/Collection.html +0 -797
  47. data/doc/Seabright/Collections.html +0 -635
  48. data/doc/Seabright/Collections/ClassMethods.html +0 -212
  49. data/doc/Seabright/ExternalIndex.html +0 -217
  50. data/doc/Seabright/History.html +0 -382
  51. data/doc/Seabright/History/ClassMethods.html +0 -276
  52. data/doc/Seabright/Indices.html +0 -324
  53. data/doc/Seabright/Indices/ClassMethods.html +0 -348
  54. data/doc/Seabright/Keys.html +0 -314
  55. data/doc/Seabright/Keys/ClassMethods.html +0 -276
  56. data/doc/Seabright/ObjectBase.html +0 -852
  57. data/doc/Seabright/ObjectBase/ClassMethods.html +0 -677
  58. data/doc/Seabright/RedisObject.html +0 -230
  59. data/doc/Seabright/References.html +0 -280
  60. data/doc/Seabright/Storage.html +0 -252
  61. data/doc/Seabright/Storage/ClassMethods.html +0 -276
  62. data/doc/Seabright/Storage/MySQL.html +0 -442
  63. data/doc/Seabright/Storage/Redis.html +0 -218
  64. data/doc/Seabright/Template.html +0 -212
  65. data/doc/Seabright/Template/ClassMethods.html +0 -166
  66. data/doc/Seabright/Timestamps.html +0 -292
  67. data/doc/Seabright/Timestamps/ClassMethods.html +0 -214
  68. data/doc/Seabright/Types.html +0 -410
  69. data/doc/Seabright/Types/ClassMethods.html +0 -308
  70. data/doc/created.rid +0 -17
  71. data/doc/images/add.png +0 -0
  72. data/doc/images/brick.png +0 -0
  73. data/doc/images/brick_link.png +0 -0
  74. data/doc/images/bug.png +0 -0
  75. data/doc/images/bullet_black.png +0 -0
  76. data/doc/images/bullet_toggle_minus.png +0 -0
  77. data/doc/images/bullet_toggle_plus.png +0 -0
  78. data/doc/images/date.png +0 -0
  79. data/doc/images/delete.png +0 -0
  80. data/doc/images/find.png +0 -0
  81. data/doc/images/loadingAnimation.gif +0 -0
  82. data/doc/images/macFFBgHack.png +0 -0
  83. data/doc/images/package.png +0 -0
  84. data/doc/images/page_green.png +0 -0
  85. data/doc/images/page_white_text.png +0 -0
  86. data/doc/images/page_white_width.png +0 -0
  87. data/doc/images/plugin.png +0 -0
  88. data/doc/images/ruby.png +0 -0
  89. data/doc/images/tag_blue.png +0 -0
  90. data/doc/images/tag_green.png +0 -0
  91. data/doc/images/transparent.png +0 -0
  92. data/doc/images/wrench.png +0 -0
  93. data/doc/images/wrench_orange.png +0 -0
  94. data/doc/images/zoom.png +0 -0
  95. data/doc/index.html +0 -125
  96. data/doc/js/darkfish.js +0 -153
  97. data/doc/js/jquery.js +0 -18
  98. data/doc/js/navigation.js +0 -142
  99. data/doc/js/search.js +0 -94
  100. data/doc/js/search_index.js +0 -1
  101. data/doc/js/searcher.js +0 -228
  102. data/doc/rdoc.css +0 -543
  103. data/doc/table_of_contents.html +0 -394
@@ -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
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module DefaultSpec
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
+ # Delicious pizza!
19
+ class DefaultedObject < RedisObject
20
+
21
+ TestValues.keys.each do |type|
22
+ send(type.to_sym,"a_#{type}".to_sym)
23
+ end
24
+ default_for :testy, "test"
25
+ default_for :a_number, 42
26
+
27
+ end
28
+
29
+ describe Seabright::DefaultValues do
30
+ before do
31
+ RedisObject.store.flushdb
32
+ end
33
+
34
+ it "returns default value" do
35
+
36
+ obj = DefaultedObject.create(TestData)
37
+
38
+ obj.testy.should eq("test")
39
+ obj.get(:a_number).should eq(27)
40
+ obj.unset(:a_number)
41
+ obj.get(:a_number).should eq(42)
42
+
43
+ end
44
+
45
+ it "returns default value after unset" do
46
+
47
+ obj = DefaultedObject.create(TestData)
48
+
49
+ obj.get(:a_number).should eq(27)
50
+ obj.unset(:a_number)
51
+ obj.get(:a_number).should eq(42)
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module FilterSpec
4
+
5
+ class FilteredObject < RedisObject
6
+
7
+ def double(k,v)
8
+ (k == :testy) && v ? [:testy,v*2] : [k,v]
9
+ end
10
+ set_filter :double
11
+
12
+ end
13
+
14
+ describe Seabright::Filters do
15
+ before do
16
+ RedisObject.store.flushdb
17
+ end
18
+
19
+ it "modifies set and gets correctly" do
20
+
21
+ obj = FilteredObject.create("test")
22
+
23
+ obj.set(:testy,"test")
24
+ obj.get(:testy).should eq("testtest")
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module IndexSpec
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
+ # Delicious pizza!
19
+ class IndexedObject < RedisObject
20
+
21
+ TestValues.keys.each do |type|
22
+ send(type.to_sym,"a_#{type}".to_sym)
23
+ end
24
+
25
+ sort_by :a_number
26
+
27
+ end
28
+
29
+ describe Seabright::Indices do
30
+ before do
31
+ RedisObject.store.flushdb
32
+ end
33
+
34
+ it "indexes on integer field" do
35
+
36
+ 5.times do
37
+ obj = IndexedObject.create(a_number: Random.rand(100))
38
+ end
39
+
40
+ IndexedObject.indexed(:a_number,3,true).count.should eq(3)
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,96 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module RenameClassSpec
4
+ # Delicious pizza!
5
+ class Pizza < RedisObject; end
6
+ # We love toppings but our current name Topping is too ambiguous!
7
+ class Topping < RedisObject; end
8
+ # Let's change the class name to PizzaTopping!
9
+ class PizzaTopping < RedisObject; end
10
+
11
+ describe Seabright::Storage::Redis, "#rename_class" do
12
+ before do
13
+ RedisObject.store.flushdb
14
+
15
+ mozzarella = Topping.create(:mozzarella)
16
+ basil = Topping.create(:basil)
17
+ tomato = Topping.create(:tomato)
18
+ garlic = Topping.create(:garlic)
19
+ oregano = Topping.create(:oregano)
20
+ olive_oil = Topping.create(:olive_oil)
21
+
22
+ marinara = Pizza.create(:marinara)
23
+ [ tomato, garlic, oregano, olive_oil ].each{|topping| marinara << topping }
24
+
25
+ margherita = Pizza.create(:margherita)
26
+ [ tomato, mozzarella, basil, olive_oil ].each{|topping| margherita << topping }
27
+ end
28
+
29
+ it "setup works" do
30
+ margherita = Pizza.find(:margherita)
31
+ marinara = Pizza.find(:marinara)
32
+ mozzarella = Topping.find(:mozzarella)
33
+ basil = Topping.find(:basil)
34
+ tomato = Topping.find(:tomato)
35
+ garlic = Topping.find(:garlic)
36
+ oregano = Topping.find(:oregano)
37
+ olive_oil = Topping.find(:olive_oil)
38
+
39
+ [ mozzarella, basil, tomato, garlic, oregano, olive_oil ].each do |topping|
40
+ topping.get(:class).should == Topping.name
41
+ topping.get(:key).should == "RenameClassSpec::Topping:#{topping.id}"
42
+ topping.get(:topping_id).should == topping.id
43
+ end
44
+
45
+ Topping.indexed(:created_at).first.should_not be_nil
46
+ Topping.indexed(:created_at).count.should == 5
47
+
48
+ [margherita, marinara].each do |pizza|
49
+ pizza.pizza_toppings.should be_nil
50
+ pizza.toppings.count.should == 4
51
+ pizza.toppings.should include(tomato.hkey)
52
+ pizza.toppings.should include(olive_oil.hkey)
53
+ end
54
+
55
+ margherita.toppings.should include(basil.hkey)
56
+ margherita.toppings.should include(mozzarella.hkey)
57
+ marinara.toppings.should include(oregano.hkey)
58
+ marinara.toppings.should include(garlic.hkey)
59
+ end
60
+
61
+ it "renames a class" do
62
+ RedisObject.store.rename_class(:"RenameClassSpec::Topping", :"RenameClassSpec::PizzaTopping")
63
+
64
+ margherita = Pizza.find(:margherita)
65
+ marinara = Pizza.find(:marinara)
66
+ mozzarella = PizzaTopping.find(:mozzarella)
67
+ basil = PizzaTopping.find(:basil)
68
+ tomato = PizzaTopping.find(:tomato)
69
+ garlic = PizzaTopping.find(:garlic)
70
+ oregano = PizzaTopping.find(:oregano)
71
+ olive_oil = PizzaTopping.find(:olive_oil)
72
+
73
+ [ mozzarella, basil, tomato, garlic, oregano, olive_oil ].each do |topping|
74
+ topping.get(:class).should == PizzaTopping.name
75
+ topping.get(:key).should == "RenameClassSpec::PizzaTopping:#{topping.id}"
76
+ topping.get(:"renameclassspec::pizzatopping_id").should == topping.id
77
+ # topping.get(:topping_id).should == nil
78
+ end
79
+
80
+ [margherita, marinara].each do |pizza|
81
+ pizza.toppings.should be_nil
82
+ pizza.pizza_toppings.count.should == 4
83
+ pizza.pizza_toppings.should include(tomato.hkey)
84
+ pizza.pizza_toppings.should include(olive_oil.hkey)
85
+ end
86
+
87
+ margherita.pizza_toppings.should include(basil.hkey)
88
+ margherita.pizza_toppings.should include(mozzarella.hkey)
89
+ marinara.pizza_toppings.should include(oregano.hkey)
90
+ marinara.pizza_toppings.should include(garlic.hkey)
91
+
92
+ PizzaTopping.indexed(:created_at).first.should_not be_nil
93
+ PizzaTopping.indexed(:created_at).count.should == 5
94
+ end
95
+ end
96
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,4 +4,35 @@ $LOAD_PATH.unshift File.dirname(__FILE__)
4
4
  require 'rubygems'
5
5
  require 'test/unit'
6
6
  require 'rspec'
7
- require 'redis_object'
7
+
8
+ require 'simplecov'
9
+ require 'coveralls'
10
+
11
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
12
+ SimpleCov::Formatter::HTMLFormatter,
13
+ Coveralls::SimpleCov::Formatter
14
+ ]
15
+ SimpleCov.start do
16
+ add_filter "_spec.rb"
17
+ add_filter "/experimental/"
18
+ add_group "Extensions", "lib/redis_object/ext/"
19
+ end
20
+
21
+ require 'redis_object'
22
+
23
+ class DebugMode
24
+ def initialize(o=nil); @opts = o; end
25
+ def verbose?; debug? && !!@opts[:verbose]; end
26
+ def debug?; !!@opts; end
27
+ end
28
+ Debug = if ENV['DEBUG']
29
+ require 'debugger'
30
+ DEBUG = true
31
+ DebugMode.new(verbose:true)
32
+ else
33
+ DEBUG = false
34
+ DebugMode.new
35
+ end
36
+
37
+ raise 'must specify TEST_DB' unless ENV['TEST_DB']
38
+ RedisObject.configure_store({adapter:'Redis', db:ENV['TEST_DB']},:global,:alias)