relaxdb 0.3.5 → 0.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.
Files changed (49) hide show
  1. data/README.textile +21 -23
  2. data/Rakefile +2 -7
  3. data/docs/spec_results.html +5 -5
  4. data/lib/more/grapher.rb +1 -1
  5. data/lib/relaxdb.rb +3 -5
  6. data/lib/relaxdb/all_delegator.rb +19 -13
  7. data/lib/relaxdb/document.rb +150 -218
  8. data/lib/relaxdb/extlib.rb +7 -1
  9. data/lib/relaxdb/migration.rb +11 -8
  10. data/lib/relaxdb/net_http_server.rb +19 -1
  11. data/lib/relaxdb/paginator.rb +30 -11
  12. data/lib/relaxdb/query.rb +1 -1
  13. data/lib/relaxdb/{belongs_to_proxy.rb → references_proxy.rb} +3 -3
  14. data/lib/relaxdb/relaxdb.rb +87 -7
  15. data/lib/relaxdb/server.rb +8 -2
  16. data/lib/relaxdb/taf2_curb_server.rb +2 -1
  17. data/lib/relaxdb/uuid_generator.rb +38 -2
  18. data/lib/relaxdb/view_by_delegator.rb +34 -0
  19. data/lib/relaxdb/view_object.rb +1 -1
  20. data/lib/relaxdb/view_uploader.rb +16 -2
  21. data/lib/relaxdb/views.rb +23 -55
  22. data/readme.rb +3 -3
  23. data/spec/all_delegator_spec.rb +52 -0
  24. data/spec/callbacks_spec.rb +4 -4
  25. data/spec/derived_properties_spec.rb +4 -4
  26. data/spec/design_doc_spec.rb +2 -2
  27. data/spec/doc_inheritable_spec.rb +2 -2
  28. data/spec/document_spec.rb +47 -25
  29. data/spec/migration_spec.rb +12 -10
  30. data/spec/qpaginate_spec.rb +88 -0
  31. data/spec/query_spec.rb +2 -2
  32. data/spec/references_proxy_spec.rb +94 -0
  33. data/spec/relaxdb_spec.rb +29 -21
  34. data/spec/server_spec.rb +4 -3
  35. data/spec/spec_helper.rb +1 -0
  36. data/spec/spec_models.rb +48 -57
  37. data/spec/uuid_generator_spec.rb +34 -0
  38. data/spec/view_by_spec.rb +62 -54
  39. data/spec/view_docs_by_spec.rb +85 -0
  40. metadata +38 -27
  41. data/lib/more/atomic_bulk_save_support.rb +0 -18
  42. data/lib/relaxdb/has_many_proxy.rb +0 -101
  43. data/lib/relaxdb/has_one_proxy.rb +0 -42
  44. data/lib/relaxdb/references_many_proxy.rb +0 -97
  45. data/spec/belongs_to_spec.rb +0 -124
  46. data/spec/has_many_spec.rb +0 -202
  47. data/spec/has_one_spec.rb +0 -123
  48. data/spec/references_many_spec.rb +0 -173
  49. data/spec/view_spec.rb +0 -23
@@ -1,42 +0,0 @@
1
- module RelaxDB
2
-
3
- class HasOneProxy
4
-
5
- def initialize(client, relationship)
6
- @client = client
7
- @relationship = relationship
8
- @target_class = @relationship.to_s.camel_case
9
- @relationship_as_viewed_by_target = client.class.name.snake_case
10
-
11
- @target = nil
12
- end
13
-
14
- def target
15
- return @target if @target
16
- @target = load_target
17
- end
18
-
19
- # All database changes performed by this method would ideally be done in a transaction
20
- def target=(new_target)
21
- # Nullify any existing relationship on assignment
22
- old_target = target
23
- if old_target
24
- old_target.send("#{@relationship_as_viewed_by_target}=".to_sym, nil)
25
- old_target.save
26
- end
27
-
28
- @target = new_target
29
- unless @target.nil?
30
- @target.send("#{@relationship_as_viewed_by_target}=".to_sym, @client)
31
- @target.save
32
- end
33
- end
34
-
35
- def load_target
36
- view_name = "#{@client.class}_#{@relationship}"
37
- RelaxDB.view(view_name, :key => @client._id).first
38
- end
39
-
40
- end
41
-
42
- end
@@ -1,97 +0,0 @@
1
- module RelaxDB
2
-
3
- class ReferencesManyProxy
4
-
5
- include Enumerable
6
-
7
- def initialize(client, relationship, opts)
8
- @client = client
9
- @relationship = relationship
10
-
11
- @target_class = opts[:class]
12
- @relationship_as_viewed_by_target = opts[:known_as].to_s
13
-
14
- @peers = resolve
15
- end
16
-
17
- def <<(obj, reciprocal_invocation=false)
18
- return false if peer_ids.include? obj._id
19
-
20
- @peers << obj if @peers
21
- peer_ids << obj._id
22
-
23
- unless reciprocal_invocation
24
- # Set the other side of the relationship, ensuring this method isn't called again
25
- obj.send(@relationship_as_viewed_by_target).send(:<<, @client, true)
26
-
27
- # Bulk save to ensure relationship is persisted on both sides
28
- RelaxDB.bulk_save! @client, obj
29
- end
30
-
31
- self
32
- end
33
-
34
- def clear
35
- @peers.each do |peer|
36
- peer.send(@relationship_as_viewed_by_target).send(:delete_from_self, @client)
37
- end
38
-
39
- # Important to resolve in the database before in memory, although an examination of the
40
- # contents of the bulk_save will look wrong as this object will still list all its peers
41
- RelaxDB.bulk_save(@client, *@peers)
42
-
43
- peer_ids.clear
44
- @peers.clear
45
- end
46
-
47
- def delete(obj)
48
- deleted = obj.send(@relationship_as_viewed_by_target).send(:delete_from_self, @client)
49
- if deleted
50
- delete_from_self(obj)
51
- RelaxDB.bulk_save(@client, obj)
52
- end
53
- deleted
54
- end
55
-
56
- def delete_from_self(obj)
57
- @peers.delete(obj)
58
- peer_ids.delete(obj._id)
59
- end
60
-
61
- def empty?
62
- peer_ids.empty?
63
- end
64
-
65
- def size
66
- peer_ids.size
67
- end
68
-
69
- def [](*args)
70
- @peers[*args]
71
- end
72
-
73
- def each(&blk)
74
- @peers.each(&blk)
75
- end
76
-
77
- def inspect
78
- @client.instance_variable_get("@#{@relationship}".to_sym).inspect
79
- end
80
-
81
- def peer_ids
82
- @client.instance_variable_get("@#{@relationship}".to_sym)
83
- end
84
-
85
- alias to_id_a peer_ids
86
-
87
- private
88
-
89
- # Resolves the actual ids into real objects via a single GET to CouchDB
90
- def resolve
91
- view_name = "#{@client.class}_#{@relationship}"
92
- @peers = RelaxDB.view(view_name, :key => @client._id)
93
- end
94
-
95
- end
96
-
97
- end
@@ -1,124 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
- require File.dirname(__FILE__) + '/spec_models.rb'
3
-
4
- describe RelaxDB::BelongsToProxy do
5
-
6
- before(:all) do
7
- setup_test_db
8
- end
9
-
10
- describe "belongs_to" do
11
-
12
- it "should return nil when accessed before assignment" do
13
- r = Rating.new
14
- r.photo.should == nil
15
- end
16
-
17
- it "should be establishable via constructor attribute" do
18
- p = Photo.new
19
- r = Rating.new :photo => p
20
- r.photo.should == p
21
- end
22
-
23
- it "should be establishable via constructor id" do
24
- p = Photo.new.save
25
- r = Rating.new(:photo_id => p._id).save
26
- r.photo.should == p
27
- end
28
-
29
- it "should establish the parent relationship when supplied a parent and saved" do
30
- p = Photo.new.save
31
- r = Rating.new
32
- r.photo = p
33
- # I'm not saying the following is correct or desired - merely codifying how things stand
34
- p.rating.should be_nil
35
- r.save
36
- p.rating.should == r
37
- end
38
-
39
- it "should establish the parent relationship when supplied a parent id and saved" do
40
- p = Photo.new.save
41
- r = Rating.new(:photo_id => p._id).save
42
- p.rating.should == r
43
- end
44
-
45
- it "should return the same object on repeated invocations" do
46
- p = Photo.new.save
47
- r = Rating.new(:photo => p).save
48
- r = RelaxDB.load(r._id)
49
- r.photo.object_id.should == r.photo.object_id
50
- end
51
-
52
- it "should be nullified when the parent is destroyed" do
53
- r = Rating.new
54
- p = Photo.new(:rating => r).save
55
- p.destroy!
56
- RelaxDB.load(r._id).photo.should be_nil
57
- end
58
-
59
- it "should be preserved across save / load boundary" do
60
- r = Rating.new
61
- p = Photo.new(:rating => r).save
62
- r = RelaxDB.load r._id
63
- r.photo.should == p
64
- end
65
-
66
- it "should be able to reference itself via its parent" do
67
- r = Rating.new
68
- p = Photo.new(:rating => r).save
69
- r = RelaxDB.load r._id
70
- r.photo.rating.should == r
71
- end
72
-
73
- it "may be used reciprocally" do
74
- C1 = Class.new(RelaxDB::Document) do
75
- belongs_to :c2
76
- end
77
- C2 = Class.new(RelaxDB::Document) do
78
- belongs_to :c1
79
- end
80
- i1, i2 = C1.new, C2.new
81
-
82
- i1.c2 = i2
83
- i1.save!
84
- i2.c1 = i1
85
- i2.save!
86
-
87
- i1 = RelaxDB.load i1._id
88
- i1.c2.should == i2
89
-
90
- i2 = RelaxDB.load i2._id
91
- i2.c1.should == i1
92
- end
93
-
94
- describe "validator" do
95
-
96
- it "should be passed the _id and object" do
97
- a = Atom.new(:_id => "atom").save!
98
- c = Class.new(RelaxDB::Document) do
99
- belongs_to :foo, :validator => lambda { |foo_id, obj| foo_id.reverse == obj._id }
100
- end
101
- c.new(:_id => "mota", :foo => a).save!
102
- end
103
-
104
- it "may be used with a predefined validator" do
105
- c = Class.new(RelaxDB::Document) do
106
- belongs_to :foo, :validator => :required
107
- end
108
- c.new.save.should be_false
109
- end
110
-
111
- it "should be provided with a default error message when validation fails" do
112
- c = Class.new(RelaxDB::Document) do
113
- belongs_to :foo, :validator => :required
114
- end
115
- x = c.new
116
- x.save
117
- x.errors[:foo].should_not be_blank
118
- end
119
-
120
- end
121
-
122
- end
123
-
124
- end
@@ -1,202 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
- require File.dirname(__FILE__) + '/spec_models.rb'
3
-
4
- describe RelaxDB::HasManyProxy do
5
-
6
- before(:all) do
7
- setup_test_db
8
- end
9
-
10
- describe "has_many" do
11
-
12
-
13
- describe "target_class in the generated view" do
14
- it "should infer the class name from the relationship if not supplied" do
15
- view = mock(:view).as_null_object
16
- RelaxDB::ViewCreator.should_receive(:has_n).with(
17
- "", # client_class
18
- :foo_bars, # relationship
19
- "FooBar", # target_class
20
- "" # relationship_to_client
21
- ).and_return view
22
- klass = Class.new(RelaxDB::Document) do
23
- has_many :foo_bars
24
- end
25
- end
26
-
27
- it "should use the class name if supplied" do
28
- view = mock(:view).as_null_object
29
- RelaxDB::ViewCreator.should_receive(:has_n).with(
30
- "", # client_class
31
- :foo_bars, # relationship
32
- "Bar", # target_class
33
- "" # relationship_to_client
34
- ).and_return view
35
- klass = Class.new(RelaxDB::Document) do
36
- has_many :foo_bars, :class => "Bar"
37
- end
38
- end
39
- end
40
-
41
- it "should be considered enumerable" do
42
- u = User.new.save
43
- u.items.should be_a_kind_of(Enumerable)
44
- end
45
-
46
- it "should actually be enumerable" do
47
- u = User.new.save
48
- u.items << Item.new(:name => "a")
49
- u.items << Item.new(:name => "b")
50
- names = u.items.inject("") { |memo, i| memo << i.name }
51
- names.should == "ab"
52
- end
53
-
54
- it "should preserve the collection across the load / save boundary" do
55
- u = User.new.save
56
- u.items << Item.new
57
- u = RelaxDB.load u._id
58
- u.items.size.should == 1
59
- end
60
-
61
- it "should work with MultiWordClassNames" do
62
- c = MultiWordChild.new
63
- m = MultiWordClass.new.save
64
- m.multi_word_children << c
65
- m = RelaxDB.load m._id
66
- m.multi_word_children[0].should == c
67
- end
68
-
69
- describe "#<<" do
70
-
71
- it "should link the added item to the parent" do
72
- u = User.new
73
- u.items << Item.new
74
- u.items[0].user.should == u
75
- end
76
-
77
- it "should return self" do
78
- u = User.new.save
79
- u.items << Item.new << Item.new
80
- u.items[0].user.should == u
81
- u.items[1].user.should == u
82
- end
83
-
84
- it "should not created duplicates when invoked with same object more than once" do
85
- u = User.new.save
86
- i = Item.new
87
- u.items << i << i
88
- u.items.size.should == 1
89
- end
90
-
91
- it "should return false when the child fails validation" do
92
- d = Dysfunctional.new
93
- r = (d.failures << Failure.new)
94
- r.should be_false
95
- d.failures.should be_empty
96
- end
97
-
98
- end
99
-
100
- describe "#=" do
101
-
102
- before(:each) do
103
- # Create the underlying views
104
- User.new(:items => [], :invites_received => [], :invites_sent => [])
105
- end
106
-
107
- it "should not attempt to save the child objects when the relationship is established" do
108
- RelaxDB.db.put_count = 0
109
- i1, i2 = Item.new(:name => "i1"), Item.new(:name => "i2")
110
- User.new(:items => [i1, i2])
111
- RelaxDB.db.put_count.should == 0
112
- end
113
-
114
- it "should preserve given relationships across save/load boundary" do
115
- i1, i2 = Item.new(:name => "i1"), Item.new(:name => "i2")
116
- u = User.new(:items => [i1, i2])
117
- RelaxDB.bulk_save u, *u.items
118
- u = RelaxDB.load u._id
119
- u.items.map { |i| i.name }.sort.join.should == "i1i2"
120
- end
121
-
122
- it "should invoke the derived properties writer" do
123
- class HmsdParent < RelaxDB::Document
124
- property :foo, :derived => [:zongs, lambda {|f, o| o.zongs.first.z / 2 }]
125
- has_many :zongs, :class => "HmsdChild"
126
- end
127
- class HmsdChild < RelaxDB::Document
128
- property :z
129
- belongs_to :hmsd_parent
130
- end
131
- oz = HmsdChild.new(:z => 10)
132
- op = HmsdParent.new(:zongs => [oz])
133
- op.foo.should == 5
134
- end
135
-
136
- end
137
-
138
- describe "#delete" do
139
-
140
- it "should nullify the belongs_to relationship" do
141
- u = User.new.save
142
- i = Item.new
143
- u.items << i
144
- u.items.delete i
145
- i.user.should be_nil
146
- RelaxDB.load(i._id).user.should be_nil
147
- end
148
-
149
- end
150
-
151
- describe "#clear" do
152
-
153
- it "should result in an empty collection" do
154
- u = User.new.save
155
- u.items << Item.new << Item.new
156
- u.items.clear
157
- u.items.should be_empty
158
- end
159
-
160
- it "should nullify all child relationships" do
161
- u = User.new.save
162
- i1, i2 = Item.new, Item.new
163
- u.items << i1
164
- u.items << i2
165
- u.items.clear
166
-
167
- i1.user.should be_nil
168
- i2.user.should be_nil
169
- RelaxDB.load(i1._id).user.should be_nil
170
- RelaxDB.load(i2._id).user.should be_nil
171
- end
172
-
173
- end
174
-
175
- describe "owner" do
176
-
177
- it "should be able to form multiple relationships with the same class of child" do
178
- u1, u2 = User.new.save, User.new.save
179
- i = Invite.new(:recipient => u2)
180
- u1.invites_sent << Invite.new
181
- RelaxDB.load(u1._id).invites_sent[0] == i
182
- RelaxDB.load(u2._id).invites_received[0] == i
183
- end
184
-
185
- describe "#destroy" do
186
-
187
- it "should nullify its child relationships" do
188
- Item.view_by :user_id
189
-
190
- u = User.new.save
191
- u.items << Item.new << Item.new
192
- u.destroy!
193
- Item.by_user_id(:key => u._id).should be_empty
194
- end
195
-
196
- end
197
-
198
- end
199
-
200
- end
201
-
202
- end