paulcarey-relaxdb 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +4 -0
- data/Rakefile +1 -1
- data/lib/relaxdb.rb +2 -0
- data/lib/relaxdb/all_delegator.rb +23 -3
- data/lib/relaxdb/design_doc.rb +5 -0
- data/lib/relaxdb/document.rb +39 -20
- data/lib/relaxdb/paginator.rb +1 -1
- data/lib/relaxdb/query.rb +1 -0
- data/lib/relaxdb/references_many_proxy.rb +5 -3
- data/lib/relaxdb/relaxdb.rb +24 -6
- data/lib/relaxdb/server.rb +11 -1
- data/lib/relaxdb/sorted_by_view.rb +6 -3
- data/lib/relaxdb/views.rb +14 -2
- data/spec/belongs_to_spec.rb +7 -0
- data/spec/design_doc_spec.rb +1 -1
- data/spec/document_spec.rb +83 -8
- data/spec/references_many_spec.rb +1 -4
- data/spec/relaxdb_spec.rb +40 -0
- data/spec/spec_models.rb +9 -0
- metadata +3 -2
data/README.textile
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
h3. What's New?
|
2
2
|
|
3
|
+
* Semantic consistency for load, load!, save and save!. The bang versions raise an exception when their more relaxed siblings would simply return nil.
|
4
|
+
|
5
|
+
* Minimal support for CouchDB validation
|
6
|
+
|
3
7
|
* Time storage changes. All Time objects are now converted to UTC and formatted as %Y/%m/%d %H:%M:%S +0000. Storing all Times as UTC should have been happening anyway. Formatting Times as above (as opposed to ISO 8601 as was done prior to 0.2.3) allows the Time strings to be passed directly to Date.new in a JavaScript interpreter.
|
4
8
|
|
5
9
|
* Pagination! CouchDB offers great support for retrieving a subset of data, but the housekeeping is tricky. RelaxDB takes care of it.
|
data/Rakefile
CHANGED
data/lib/relaxdb.rb
CHANGED
@@ -13,6 +13,8 @@ require 'tempfile'
|
|
13
13
|
$:.unshift(File.dirname(__FILE__)) unless
|
14
14
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
15
15
|
|
16
|
+
require 'relaxdb/validators'
|
17
|
+
|
16
18
|
require 'relaxdb/all_delegator'
|
17
19
|
require 'relaxdb/belongs_to_proxy'
|
18
20
|
require 'relaxdb/design_doc'
|
@@ -6,6 +6,7 @@ module RelaxDB
|
|
6
6
|
# FooDoc.all.sorted_by(:att1, :att2) - returns all docs in CouchDB of type FooDoc sorted by att1, then att2
|
7
7
|
# FooDoc.all.sorted_by(:att1) { |q| q.key("bar") } - returns all docs of type FooDoc where att1 equals "bar"
|
8
8
|
# FooDoc.all.destroy! - does what it says on the tin
|
9
|
+
# FooDoc.all.size - issues a query to a reduce function that returns the total number of docs for that class
|
9
10
|
#
|
10
11
|
class AllDelegator < Delegator
|
11
12
|
|
@@ -15,10 +16,10 @@ module RelaxDB
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def __getobj__
|
18
|
-
view_path = "_view/#{@class_name}/all"
|
19
|
-
|
19
|
+
view_path = "_view/#{@class_name}/all?reduce=false"
|
20
|
+
map, reduce = ViewCreator.all(@class_name)
|
20
21
|
|
21
|
-
|
22
|
+
RelaxDB.retrieve(view_path, @class_name, "all", map, reduce)
|
22
23
|
end
|
23
24
|
|
24
25
|
def sorted_by(*atts)
|
@@ -42,6 +43,25 @@ module RelaxDB
|
|
42
43
|
o.destroy!
|
43
44
|
end
|
44
45
|
end
|
46
|
+
|
47
|
+
# This is pretty ugly - this pattern is now spread over three
|
48
|
+
# places (sorted_by_view, relaxdb and here)
|
49
|
+
# Consolidation needed
|
50
|
+
def size
|
51
|
+
view_path = "_view/#{@class_name}/all"
|
52
|
+
map, reduce = ViewCreator.all(@class_name)
|
53
|
+
|
54
|
+
begin
|
55
|
+
resp = RelaxDB.db.get(view_path)
|
56
|
+
rescue => e
|
57
|
+
DesignDocument.get(@class_name).add_map_view("all", map).
|
58
|
+
add_reduce_view("all", reduce).save
|
59
|
+
resp = RelaxDB.db.get(view_path)
|
60
|
+
end
|
61
|
+
|
62
|
+
data = JSON.parse(resp.body)
|
63
|
+
data["rows"][0] ? data["rows"][0]["value"] : 0
|
64
|
+
end
|
45
65
|
|
46
66
|
end
|
47
67
|
|
data/lib/relaxdb/design_doc.rb
CHANGED
@@ -15,6 +15,11 @@ module RelaxDB
|
|
15
15
|
add_view(view_name, "reduce", function)
|
16
16
|
end
|
17
17
|
|
18
|
+
def add_validation_func(function)
|
19
|
+
@data["validate_doc_update"] = function
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
18
23
|
def add_view(view_name, type, function)
|
19
24
|
@data["views"] ||= {}
|
20
25
|
@data["views"][view_name] ||= {}
|
data/lib/relaxdb/document.rb
CHANGED
@@ -2,6 +2,8 @@ module RelaxDB
|
|
2
2
|
|
3
3
|
class Document
|
4
4
|
|
5
|
+
include RelaxDB::Validators
|
6
|
+
|
5
7
|
# Used to store validation messages
|
6
8
|
attr_accessor :errors
|
7
9
|
|
@@ -29,11 +31,7 @@ module RelaxDB
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
if opts[:validator]
|
33
|
-
define_method("validate_#{prop}") do |prop_val|
|
34
|
-
opts[:validator].call(prop_val)
|
35
|
-
end
|
36
|
-
end
|
34
|
+
create_validator(prop, opts[:validator]) if opts[:validator]
|
37
35
|
|
38
36
|
if opts[:validation_msg]
|
39
37
|
define_method("#{prop}_validation_msg") do
|
@@ -47,6 +45,18 @@ module RelaxDB
|
|
47
45
|
# Ensure that classes that don't define their own properties still function as CouchDB objects
|
48
46
|
@properties ||= [:_id, :_rev]
|
49
47
|
end
|
48
|
+
|
49
|
+
def self.create_validator(att, v)
|
50
|
+
define_method("validate_#{att}") do |att_val|
|
51
|
+
if v.is_a? Proc
|
52
|
+
v.call(att_val)
|
53
|
+
elsif respond_to? "validator_#{v}"
|
54
|
+
send("validator_#{v}", att_val)
|
55
|
+
else
|
56
|
+
send(v, att_val)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
50
60
|
|
51
61
|
def properties
|
52
62
|
self.class.properties
|
@@ -100,7 +110,7 @@ module RelaxDB
|
|
100
110
|
prop_val = instance_variable_get("@#{prop}".to_sym)
|
101
111
|
s << ", #{prop}: #{prop_val.inspect}" if prop_val
|
102
112
|
end
|
103
|
-
self.class.belongs_to_rels.each do |relationship|
|
113
|
+
self.class.belongs_to_rels.each do |relationship, opts|
|
104
114
|
id = instance_variable_get("@#{relationship}_id".to_sym)
|
105
115
|
s << ", #{relationship}_id: #{id}" if id
|
106
116
|
end
|
@@ -142,7 +152,7 @@ module RelaxDB
|
|
142
152
|
return false unless validates?
|
143
153
|
return false unless before_save
|
144
154
|
|
145
|
-
set_created_at if
|
155
|
+
set_created_at if new_document?
|
146
156
|
|
147
157
|
resp = RelaxDB.db.put("#{_id}", to_json)
|
148
158
|
self._rev = JSON.parse(resp.body)["rev"]
|
@@ -152,6 +162,10 @@ module RelaxDB
|
|
152
162
|
self
|
153
163
|
end
|
154
164
|
|
165
|
+
def save!
|
166
|
+
save || raise(DocumentNotSaved)
|
167
|
+
end
|
168
|
+
|
155
169
|
def validates?
|
156
170
|
total_success = true
|
157
171
|
properties.each do |prop|
|
@@ -166,20 +180,24 @@ module RelaxDB
|
|
166
180
|
total_success &= success
|
167
181
|
end
|
168
182
|
end
|
169
|
-
|
183
|
+
|
184
|
+
# Unsure whether to pass the id or the doc itself - id is all I need right now
|
185
|
+
self.class.belongs_to_rels.each do |rel, opts|
|
186
|
+
if methods.include? "validate_#{rel}"
|
187
|
+
rel_val = instance_variable_get("@#{rel}_id")
|
188
|
+
success = send("validate_#{rel}", rel_val) rescue false
|
189
|
+
total_success &= success
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
170
193
|
total_success
|
171
194
|
end
|
172
|
-
|
173
|
-
def
|
174
|
-
true
|
175
|
-
end
|
176
|
-
|
177
|
-
# Hmm. Rename... never_saved? newnew?
|
178
|
-
def unsaved?
|
195
|
+
|
196
|
+
def new_document?
|
179
197
|
@_rev.nil?
|
180
198
|
end
|
181
|
-
alias_method :new_record?, :
|
182
|
-
alias_method :
|
199
|
+
alias_method :new_record?, :new_document?
|
200
|
+
alias_method :unsaved?, :new_document?
|
183
201
|
|
184
202
|
def to_param
|
185
203
|
self._id
|
@@ -198,8 +216,8 @@ module RelaxDB
|
|
198
216
|
proxy = instance_variable_get(proxy_sym)
|
199
217
|
unless proxy
|
200
218
|
proxy = opts ? klass.new(self, relationship, opts) : klass.new(self, relationship)
|
219
|
+
instance_variable_set(proxy_sym, proxy)
|
201
220
|
end
|
202
|
-
instance_variable_set(proxy_sym, proxy)
|
203
221
|
proxy
|
204
222
|
end
|
205
223
|
|
@@ -208,8 +226,8 @@ module RelaxDB
|
|
208
226
|
other && _id == other._id
|
209
227
|
end
|
210
228
|
|
211
|
-
#
|
212
|
-
#
|
229
|
+
# If you're using this method, read the specs and make sure you understand
|
230
|
+
# how it can be used and how it shouldn't be used
|
213
231
|
def self.references_many(relationship, opts={})
|
214
232
|
# Treat the representation as a standard property
|
215
233
|
properties << relationship
|
@@ -293,6 +311,7 @@ module RelaxDB
|
|
293
311
|
instance_variable_get("@#{relationship}_id")
|
294
312
|
end
|
295
313
|
|
314
|
+
create_validator(relationship, opts[:validator]) if opts[:validator]
|
296
315
|
end
|
297
316
|
|
298
317
|
def self.belongs_to_rels
|
data/lib/relaxdb/paginator.rb
CHANGED
@@ -15,7 +15,7 @@ module RelaxDB
|
|
15
15
|
|
16
16
|
def total_doc_count(design_doc, view_name)
|
17
17
|
result = RelaxDB.view(design_doc, view_name) do |q|
|
18
|
-
q.
|
18
|
+
q.reduce(true)
|
19
19
|
q.startkey(@orig_paginate_params.startkey).endkey(@orig_paginate_params.endkey).descending(@orig_paginate_params.descending)
|
20
20
|
end
|
21
21
|
|
data/lib/relaxdb/query.rb
CHANGED
@@ -78,12 +78,14 @@ module RelaxDB
|
|
78
78
|
def inspect
|
79
79
|
@client.instance_variable_get("@#{@relationship}".to_sym).inspect
|
80
80
|
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
81
|
+
|
84
82
|
def peer_ids
|
85
83
|
@client.instance_variable_get("@#{@relationship}".to_sym)
|
86
84
|
end
|
85
|
+
|
86
|
+
alias to_id_a peer_ids
|
87
|
+
|
88
|
+
private
|
87
89
|
|
88
90
|
# Resolves the actual ids into real objects via a single GET to CouchDB. Called internally by each
|
89
91
|
def resolve
|
data/lib/relaxdb/relaxdb.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module RelaxDB
|
2
|
+
|
3
|
+
class NotFound < StandardError; end
|
4
|
+
class DocumentNotSaved < StandardError; end
|
2
5
|
|
3
6
|
@@db = nil
|
4
7
|
|
@@ -49,22 +52,37 @@ module RelaxDB
|
|
49
52
|
|
50
53
|
def load(*ids)
|
51
54
|
if ids.size == 1
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
begin
|
56
|
+
resp = db.get(ids[0])
|
57
|
+
data = JSON.parse(resp.body)
|
58
|
+
create_object(data)
|
59
|
+
rescue HTTP_404
|
60
|
+
nil
|
61
|
+
end
|
55
62
|
else
|
56
63
|
resp = db.post("_all_docs?include_docs=true", {:keys => ids}.to_json)
|
57
64
|
data = JSON.parse(resp.body)
|
58
|
-
data["rows"].map { |row| create_object(row["doc"]) }
|
65
|
+
data["rows"].map { |row| row["doc"] ? create_object(row["doc"]) : nil }
|
59
66
|
end
|
60
67
|
end
|
61
68
|
|
69
|
+
def load!(*ids)
|
70
|
+
res = load(*ids)
|
71
|
+
|
72
|
+
raise NotFound if res == nil
|
73
|
+
raise NotFound if res.respond_to?(:include?) && res.include?(nil)
|
74
|
+
|
75
|
+
res
|
76
|
+
end
|
77
|
+
|
62
78
|
# Used internally by RelaxDB
|
63
|
-
def retrieve(view_path, design_doc=nil, view_name=nil,
|
79
|
+
def retrieve(view_path, design_doc=nil, view_name=nil, map_func=nil, reduce_func=nil)
|
64
80
|
begin
|
65
81
|
resp = db.get(view_path)
|
66
82
|
rescue => e
|
67
|
-
DesignDocument.get(design_doc).add_map_view(view_name,
|
83
|
+
dd = DesignDocument.get(design_doc).add_map_view(view_name, map_func)
|
84
|
+
dd.add_reduce_view(view_name, reduce_func) if reduce_func
|
85
|
+
dd.save
|
68
86
|
resp = db.get(view_path)
|
69
87
|
end
|
70
88
|
|
data/lib/relaxdb/server.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
module RelaxDB
|
2
|
+
|
3
|
+
class HTTP_404 < StandardError; end
|
4
|
+
class HTTP_409 < StandardError; end
|
2
5
|
|
3
6
|
class Server
|
4
7
|
|
@@ -46,7 +49,14 @@ module RelaxDB
|
|
46
49
|
private
|
47
50
|
|
48
51
|
def handle_error(req, res)
|
49
|
-
|
52
|
+
msg = "#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}"
|
53
|
+
begin
|
54
|
+
klass = RelaxDB.const_get("HTTP_#{res.code}")
|
55
|
+
e = klass.new(msg)
|
56
|
+
rescue
|
57
|
+
e = RuntimeError.new(msg)
|
58
|
+
end
|
59
|
+
|
50
60
|
raise e
|
51
61
|
end
|
52
62
|
end
|
@@ -25,7 +25,11 @@ module RelaxDB
|
|
25
25
|
def reduce_function
|
26
26
|
<<-QUERY
|
27
27
|
function(keys, values, rereduce) {
|
28
|
-
|
28
|
+
if (rereduce) {
|
29
|
+
return sum(values);
|
30
|
+
} else {
|
31
|
+
return values.length;
|
32
|
+
}
|
29
33
|
}
|
30
34
|
QUERY
|
31
35
|
end
|
@@ -42,8 +46,7 @@ module RelaxDB
|
|
42
46
|
# to false if it hasn't already been set.
|
43
47
|
query.reduce(false) if query.reduce.nil?
|
44
48
|
|
45
|
-
|
46
|
-
method = query.keys ? (query.group(true) && :post) : :get
|
49
|
+
method = query.keys ? :post : :get
|
47
50
|
|
48
51
|
begin
|
49
52
|
resp = RelaxDB.db.send(method, query.view_path, query.keys)
|
data/lib/relaxdb/views.rb
CHANGED
@@ -3,13 +3,25 @@ module RelaxDB
|
|
3
3
|
class ViewCreator
|
4
4
|
|
5
5
|
def self.all(target_class)
|
6
|
-
|
6
|
+
map = <<-QUERY
|
7
7
|
function(doc) {
|
8
8
|
if(doc.class == "${target_class}")
|
9
9
|
emit(null, doc);
|
10
10
|
}
|
11
11
|
QUERY
|
12
|
-
|
12
|
+
map.sub!("${target_class}", target_class.to_s)
|
13
|
+
|
14
|
+
reduce = <<-QUERY
|
15
|
+
function(keys, values, rereduce) {
|
16
|
+
if (rereduce) {
|
17
|
+
return sum(values);
|
18
|
+
} else {
|
19
|
+
return values.length;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
QUERY
|
23
|
+
|
24
|
+
[map, reduce]
|
13
25
|
end
|
14
26
|
|
15
27
|
def self.has_n(target_class, relationship_to_client)
|
data/spec/belongs_to_spec.rb
CHANGED
@@ -74,6 +74,13 @@ describe RelaxDB::BelongsToProxy do
|
|
74
74
|
r = RelaxDB.load r._id
|
75
75
|
r.photo.rating.should == r
|
76
76
|
end
|
77
|
+
|
78
|
+
it "should function with the required validator" do
|
79
|
+
c = Class.new(RelaxDB::Document) do
|
80
|
+
belongs_to :foo, :validator => :required
|
81
|
+
end
|
82
|
+
c.new.save.should be_false
|
83
|
+
end
|
77
84
|
|
78
85
|
end
|
79
86
|
|
data/spec/design_doc_spec.rb
CHANGED
@@ -26,7 +26,7 @@ describe RelaxDB::DesignDocument do
|
|
26
26
|
it "should delete the corresponding document from CouchDB" do
|
27
27
|
dd = RelaxDB::DesignDocument.get("foo").save
|
28
28
|
dd.destroy!
|
29
|
-
|
29
|
+
RelaxDB.load("_design%2Ffoo").should be_nil
|
30
30
|
end
|
31
31
|
|
32
32
|
end
|
data/spec/document_spec.rb
CHANGED
@@ -37,6 +37,17 @@ describe RelaxDB::Document do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
end
|
40
|
+
|
41
|
+
describe "#initialize" do
|
42
|
+
|
43
|
+
it "may be overridden by inheriting classes" do
|
44
|
+
i = Initiative.new(:x => "y").save
|
45
|
+
i = RelaxDB.load(i._id)
|
46
|
+
i.x.should == "y"
|
47
|
+
i.foo.should == :bar
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
40
51
|
|
41
52
|
describe "#to_json" do
|
42
53
|
|
@@ -84,6 +95,24 @@ describe RelaxDB::Document do
|
|
84
95
|
|
85
96
|
end
|
86
97
|
|
98
|
+
describe "#save!" do
|
99
|
+
|
100
|
+
it "should save objects" do
|
101
|
+
a = Atom.new.save
|
102
|
+
RelaxDB.load(a._id).should == a
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should throw an exception when an object is not saved" do
|
106
|
+
r = Class.new(RelaxDB::Document) do
|
107
|
+
property :thumbs_up, :validator => lambda { false }
|
108
|
+
end
|
109
|
+
lambda do
|
110
|
+
r.new.save!
|
111
|
+
end.should raise_error(RelaxDB::DocumentNotSaved)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
87
116
|
describe "user defined property reader" do
|
88
117
|
|
89
118
|
it "should not effect normal operation" do
|
@@ -119,7 +148,8 @@ describe RelaxDB::Document do
|
|
119
148
|
p.str.should == "foo"
|
120
149
|
p.num.should == 19.30
|
121
150
|
p.true_bool.should be_true
|
122
|
-
p.false_bool.
|
151
|
+
# p.false_bool.should be_false
|
152
|
+
p.false_bool.should_not be
|
123
153
|
p.created_at.should be_close(now, 1)
|
124
154
|
p.empty.should be_nil
|
125
155
|
end
|
@@ -136,7 +166,7 @@ describe RelaxDB::Document do
|
|
136
166
|
|
137
167
|
it "should delete the corresponding document from CouchDB" do
|
138
168
|
p = Atom.new.save.destroy!
|
139
|
-
|
169
|
+
RelaxDB.load(p._id).should be_nil
|
140
170
|
end
|
141
171
|
|
142
172
|
it "should prevent the object from being resaved" do
|
@@ -195,6 +225,21 @@ describe RelaxDB::Document do
|
|
195
225
|
|
196
226
|
end
|
197
227
|
|
228
|
+
describe ".all.size" do
|
229
|
+
|
230
|
+
it "should return the total number of docs" do
|
231
|
+
docs = []
|
232
|
+
100.times { docs << Atom.new }
|
233
|
+
RelaxDB.bulk_save(*docs)
|
234
|
+
Atom.all.size.should == 100
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should return 0 when no docs exist" do
|
238
|
+
Atom.all.size.should == 0
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
198
243
|
describe ".all.sorted_by" do
|
199
244
|
|
200
245
|
it "should sort ascending by default" do
|
@@ -222,6 +267,17 @@ describe RelaxDB::Document do
|
|
222
267
|
posts[1].content.should == "late"
|
223
268
|
end
|
224
269
|
|
270
|
+
it "should return the count when queried with reduce=true" do
|
271
|
+
docs = []
|
272
|
+
100.times { |i| docs << Primitives.new(:num => i) }
|
273
|
+
RelaxDB.bulk_save(*docs)
|
274
|
+
# Create the view
|
275
|
+
Primitives.all.sorted_by(:num)
|
276
|
+
res = RelaxDB.view("Primitives", "all_sorted_by_num") { |q| q.reduce(true) }
|
277
|
+
count = RelaxDB.reduce_result(res)
|
278
|
+
count.should == 100
|
279
|
+
end
|
280
|
+
|
225
281
|
describe "results" do
|
226
282
|
|
227
283
|
it "should be retrievable by exact criteria" do
|
@@ -307,7 +363,7 @@ describe RelaxDB::Document do
|
|
307
363
|
|
308
364
|
it "should prevent an object from being saved if it throws an exception" do
|
309
365
|
r = Class.new(RelaxDB::Document) do
|
310
|
-
property :thumbs_up, :validator => lambda { raise
|
366
|
+
property :thumbs_up, :validator => lambda { raise }
|
311
367
|
end
|
312
368
|
r.new.save.should be_false
|
313
369
|
end
|
@@ -331,8 +387,8 @@ describe RelaxDB::Document do
|
|
331
387
|
|
332
388
|
it "should perform all validations" do
|
333
389
|
r = Class.new(RelaxDB::Document) do
|
334
|
-
property :foo, :validator => lambda {
|
335
|
-
property :bar, :validator => lambda {
|
390
|
+
property :foo, :validator => lambda { raise }, :validation_msg => "oof"
|
391
|
+
property :bar, :validator => lambda { raise }, :validation_msg => "rab"
|
336
392
|
end
|
337
393
|
x = r.new
|
338
394
|
x.save
|
@@ -359,13 +415,32 @@ describe RelaxDB::Document do
|
|
359
415
|
it "may be a method" do
|
360
416
|
r = Class.new(RelaxDB::Document) do
|
361
417
|
property :thumbs_up, :validator => :count_em
|
362
|
-
def count_em
|
363
|
-
|
418
|
+
def count_em(tu)
|
419
|
+
tu >=0 && tu < 3
|
364
420
|
end
|
365
421
|
end
|
366
|
-
r.new.save.should
|
422
|
+
r.new(:thumbs_up => 1).save.should be
|
367
423
|
end
|
368
424
|
|
369
425
|
end
|
370
426
|
|
427
|
+
describe "predefined validator" do
|
428
|
+
|
429
|
+
it "should be invoked when a symbol clash exists" do
|
430
|
+
c = Class.new(RelaxDB::Document) do
|
431
|
+
property :foo, :validator => :required
|
432
|
+
def required; raise; end;
|
433
|
+
end
|
434
|
+
c.new(:foo => :bar).save.should be
|
435
|
+
end
|
436
|
+
|
437
|
+
it "should prevent an object from being saved if validation fails" do
|
438
|
+
c = Class.new(RelaxDB::Document) do
|
439
|
+
property :foo, :validator => :required
|
440
|
+
end
|
441
|
+
c.new.save.should be_false
|
442
|
+
end
|
443
|
+
|
444
|
+
end
|
445
|
+
|
371
446
|
end
|
@@ -13,10 +13,7 @@ describe RelaxDB::ReferencesManyProxy do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "references_many" do
|
16
|
-
|
17
|
-
it "is now deprecated and will be removed in the near future" do
|
18
|
-
end
|
19
|
-
|
16
|
+
|
20
17
|
it "should preserve the relationships across the save / load boundary" do
|
21
18
|
p = Photo.new
|
22
19
|
t = Tag.new
|
data/spec/relaxdb_spec.rb
CHANGED
@@ -73,6 +73,46 @@ describe RelaxDB do
|
|
73
73
|
ar2.should == a2
|
74
74
|
end
|
75
75
|
|
76
|
+
it "should return nil when given a id for a non existant doc" do
|
77
|
+
RelaxDB.load("nothere").should be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return an array with correctly placed nils when given a list containing non existant doc ids" do
|
81
|
+
a1, a2 = Atom.new.save, Atom.new.save
|
82
|
+
res = RelaxDB.load nil, a1._id, nil, a2._id, nil
|
83
|
+
res.should == [nil, a1, nil, a2, nil]
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".load!" do
|
89
|
+
|
90
|
+
it "should load a single document" do
|
91
|
+
a = Atom.new.save
|
92
|
+
ar = RelaxDB.load! a._id
|
93
|
+
ar.should == a
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should load multiple documents" do
|
97
|
+
a1, a2 = Atom.new.save, Atom.new.save
|
98
|
+
ar1, ar2 = RelaxDB.load! a1._id, a2._id
|
99
|
+
ar1.should == a1
|
100
|
+
ar2.should == a2
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should throw an exception if given a single id for a non-existant doc" do
|
104
|
+
lambda do
|
105
|
+
RelaxDB.load! "nothere"
|
106
|
+
end.should raise_error(RelaxDB::NotFound)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should throw an exception if any of a list of doc ids is for a non-existant doc" do
|
110
|
+
a = Atom.new.save
|
111
|
+
lambda do
|
112
|
+
RelaxDB.load! nil, a._id
|
113
|
+
end.should raise_error(RelaxDB::NotFound)
|
114
|
+
end
|
115
|
+
|
76
116
|
end
|
77
117
|
|
78
118
|
describe ".view" do
|
data/spec/spec_models.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paulcarey-relaxdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Carey
|
@@ -9,7 +9,7 @@ autorequire: relaxdb
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-12-26 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- lib/relaxdb/server.rb
|
69
69
|
- lib/relaxdb/sorted_by_view.rb
|
70
70
|
- lib/relaxdb/uuid_generator.rb
|
71
|
+
- lib/relaxdb/validators
|
71
72
|
- lib/relaxdb/view_object.rb
|
72
73
|
- lib/relaxdb/view_result.rb
|
73
74
|
- lib/relaxdb/view_uploader.rb
|