public
Description: Plug-and-play data persistence created for small Ruby web applications.
Homepage: http://stone.rubyforge.org
Clone URL: git://github.com/ndemonner/stone.git
Radically changed how queries work.

* Symbol has been extended to include special query methods
* Old parse_conditions method was dropped, replaced with MUCH cleaner 
version
* Added Query class to handle queries
* All in all, new queries are much safer and far stabler
ndemonner (author)
Sun Apr 13 16:05:13 -0700 2008
commit  ac3c0620ee1bc9a190709712568179e68521c4cc
tree    0abb88b889d05125ffab269a15b930755835f937
parent  d6b1774244f972ac97d89249cf29e2829e867d5b
...
9
10
11
 
12
 
13
14
15
...
9
10
11
12
13
14
15
16
17
0
@@ -9,7 +9,9 @@ config/requirements.rb
0
 lib/stone.rb
0
 lib/stone/callbacks.rb
0
 lib/stone/core_ext/string.rb
0
+lib/stone/core_ext/symbol.rb
0
 lib/stone/data_store.rb
0
+lib/stone/query.rb
0
 lib/stone/resource.rb
0
 lib/stone/utilities.rb
0
 lib/stone/version.rb
...
7
8
9
 
 
10
11
12
...
7
8
9
10
11
12
13
14
0
@@ -7,6 +7,8 @@ require 'yaml'
0
 require 'fastercsv'
0
 
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/core_ext/string')
0
+require File.expand_path(File.dirname(__FILE__) + '/stone/core_ext/symbol')
0
+require File.expand_path(File.dirname(__FILE__) + '/stone/query')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/data_store')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/callbacks')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/resource')
...
137
138
139
140
 
141
142
143
...
233
234
235
 
 
 
236
237
238
...
278
279
280
281
 
282
283
284
285
286
 
287
288
289
...
332
333
334
 
335
336
337
338
339
340
 
 
 
 
 
 
 
 
 
 
341
342
343
344
345
346
 
347
348
349
350
 
 
 
 
 
351
352
353
...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
 
 
 
 
 
 
419
420
 
 
421
422
423
...
137
138
139
 
140
141
142
143
...
233
234
235
236
237
238
239
240
241
...
281
282
283
 
284
285
286
287
288
289
290
291
292
293
...
336
337
338
339
340
 
 
 
 
 
341
342
343
344
345
346
347
348
349
350
351
352
 
 
 
 
353
354
355
356
357
358
359
360
361
362
363
364
365
...
393
394
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
397
398
399
400
401
402
 
403
404
405
406
407
0
@@ -137,7 +137,7 @@ module Stone
0
     def has_many(resource, *args)
0
       self.class_eval <<-EOS, __FILE__, __LINE__
0
         def #{resource.to_s}
0
- #{resource.to_s.singularize.titlecase}.all("#{self.to_s.downcase}_id == "+self.id.to_s)
0
+ #{resource.to_s.singularize.titlecase}.all("#{self.to_s.downcase}_id".to_sym.equals => self.id)
0
         end
0
       EOS
0
     end
0
@@ -233,6 +233,9 @@ module Stone
0
       false
0
     end
0
     
0
+ # Puts the attribute changes in +hash+
0
+ # === Parameters
0
+ # +hash+:: the attributes to change
0
     def update_attributes(hash)
0
       hash.each_key do |k|
0
         if hash[k].is_a? Hash
0
@@ -278,12 +281,13 @@ module Stone
0
           return false
0
         end
0
         if field[:unique] == true
0
- return false if self.class.first("#{field[:name]} == '#{self.send(field[:name])}'") && !self.already_exists?
0
+ return false if self.class.first(field[:name] => self.send(field[:name])) && !self.already_exists?
0
         end
0
       end
0
       true
0
     end
0
     
0
+ # Finds out if the object is already in the current DataStore instance
0
     def already_exists?
0
       DataStore.determine_save_method(self, @@store) == :put
0
     end
0
@@ -332,22 +336,30 @@ module Stone
0
     # DataStore instance
0
     def find(conditions, key) #:doc:
0
       objs = []
0
+
0
       if conditions.is_a? Hash
0
- raise "Resource.find(Hash) expects a single key, value pair" \
0
- unless conditions.size == 1
0
- conds = conditions.to_a.flatten
0
- @@store.resources[key].each do |o|
0
- objs << o[1] if o[1].send(conds[0]) == conds[1]
0
+ unless conditions.to_a.flatten.map {|e| e.is_a? Query}.include?(true)
0
+ conds = conditions.to_a.flatten
0
+ @@store.resources[key].each do |o|
0
+ objs << o[1] if o[1].send(conds[0]) == conds[1]
0
+ end
0
+ else
0
+ parsed_conditions = parse_conditions(conditions)
0
+ @@store.resources[key].each do |o|
0
+ objs << o[1] if matches_conditions?(o[1], parsed_conditions)
0
+ end
0
         end
0
       else
0
- parsed_conditions = parse_conditions(conditions)
0
- @@store.resources[key].each do |o|
0
- objs << o[1] if matches_conditions?(o[1], parsed_conditions)
0
- end
0
+ raise "Resource.find expects a Hash, got a #{conditions.class}"
0
       end
0
       objs
0
     end
0
     
0
+ # Checks the list of fields for a given +klass+ to see if +field+
0
+ # is included
0
+ # === Parameters
0
+ # +field+:: The field to look for
0
+ # +klass+:: The class to look in
0
     def field_declared?(field,klass)
0
       @@fields[klass.to_s.make_key].each do |f|
0
         return true if f[:name] == field
0
@@ -381,43 +393,15 @@ module Stone
0
       eval(tf_ary.join)
0
     end
0
     
0
- # Accepts +conditions+ like
0
- # "name.include?('nick') && email == 'nick@bzzybee.com"
0
- # and turns them into an +ary+ of expressions and their conditionals
0
- # === Parameters
0
- # +conditions+:: The plain string conditions
0
- def parse_conditions(conditions) #:doc:
0
- ary = []
0
- # Facets breaks for some reason on single condition expressions
0
- # e.g. "name == 'Nick DeMonner'"
0
- # but not on multiple ones like
0
- # "name == 'Nick DeMonner' && blah.include?('blah')"
0
- begin
0
- expr = conditions.split(/\s+&{2}|\|{2}\s+/)
0
- rescue
0
- expr = [conditions]
0
- end
0
- op = conditions.scan(/&{2}|\|{2}/)
0
- expr.each_with_index do |e,i|
0
- ary << e.strip
0
- ary << op[i] if op[i]
0
- end
0
- # convert each expr into an obj.meth(arg) format
0
- # so that name == 'nick' becomes name.==('nick')
0
- ary.each_with_index do |e,i|
0
- if i % 2 == 0 && e.split.size != 1 && !e.match(/.+(.+)/)
0
- expr_ary = e.split
0
- expr_ary[0] = expr_ary[0] + "."
0
- expr_ary[1] = expr_ary[1] + "("
0
- if expr_ary.size % 2 == 0
0
- expr_ary[expr_ary.size-1] = " " + expr_ary[expr_ary.size-1] + ")"
0
- else
0
- expr_ary[expr_ary.size-1] = expr_ary[expr_ary.size-1] + ")"
0
- end
0
- ary[i] = expr_ary.join
0
- end
0
+ # Turns conditions into a set of expressions that can be evaluated
0
+ def parse_conditions(hash)
0
+ conds = []
0
+ hash.each do |k,v|
0
+ conds << k.expression_for(v)
0
+ conds << "&&"
0
       end
0
- ary
0
+ conds.pop
0
+ conds
0
     end
0
   end # Resource
0
   
...
9
10
11
 
12
 
13
14
15
...
9
10
11
12
13
14
15
16
17
0
@@ -9,7 +9,9 @@ config/requirements.rb
0
 lib/stone.rb
0
 lib/stone/callbacks.rb
0
 lib/stone/core_ext/string.rb
0
+lib/stone/core_ext/symbol.rb
0
 lib/stone/data_store.rb
0
+lib/stone/query.rb
0
 lib/stone/resource.rb
0
 lib/stone/utilities.rb
0
 lib/stone/version.rb
...
7
8
9
 
 
10
11
12
...
7
8
9
10
11
12
13
14
0
@@ -7,6 +7,8 @@ require 'yaml'
0
 require 'fastercsv'
0
 
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/core_ext/string')
0
+require File.expand_path(File.dirname(__FILE__) + '/stone/core_ext/symbol')
0
+require File.expand_path(File.dirname(__FILE__) + '/stone/query')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/data_store')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/callbacks')
0
 require File.expand_path(File.dirname(__FILE__) + '/stone/resource')
...
137
138
139
140
 
141
142
143
...
233
234
235
 
 
 
236
237
238
...
278
279
280
281
 
282
283
284
285
286
 
287
288
289
...
332
333
334
 
335
336
337
338
339
340
 
 
 
 
 
 
 
 
 
 
341
342
343
344
345
346
 
347
348
349
350
 
 
 
 
 
351
352
353
...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
 
 
 
 
 
 
419
420
 
 
421
422
423
...
137
138
139
 
140
141
142
143
...
233
234
235
236
237
238
239
240
241
...
281
282
283
 
284
285
286
287
288
289
290
291
292
293
...
336
337
338
339
340
 
 
 
 
 
341
342
343
344
345
346
347
348
349
350
351
352
 
 
 
 
353
354
355
356
357
358
359
360
361
362
363
364
365
...
393
394
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
397
398
399
400
401
402
 
403
404
405
406
407
0
@@ -137,7 +137,7 @@ module Stone
0
     def has_many(resource, *args)
0
       self.class_eval <<-EOS, __FILE__, __LINE__
0
         def #{resource.to_s}
0
- #{resource.to_s.singularize.titlecase}.all("#{self.to_s.downcase}_id == "+self.id.to_s)
0
+ #{resource.to_s.singularize.titlecase}.all("#{self.to_s.downcase}_id".to_sym.equals => self.id)
0
         end
0
       EOS
0
     end
0
@@ -233,6 +233,9 @@ module Stone
0
       false
0
     end
0
     
0
+ # Puts the attribute changes in +hash+
0
+ # === Parameters
0
+ # +hash+:: the attributes to change
0
     def update_attributes(hash)
0
       hash.each_key do |k|
0
         if hash[k].is_a? Hash
0
@@ -278,12 +281,13 @@ module Stone
0
           return false
0
         end
0
         if field[:unique] == true
0
- return false if self.class.first("#{field[:name]} == '#{self.send(field[:name])}'") && !self.already_exists?
0
+ return false if self.class.first(field[:name] => self.send(field[:name])) && !self.already_exists?
0
         end
0
       end
0
       true
0
     end
0
     
0
+ # Finds out if the object is already in the current DataStore instance
0
     def already_exists?
0
       DataStore.determine_save_method(self, @@store) == :put
0
     end
0
@@ -332,22 +336,30 @@ module Stone
0
     # DataStore instance
0
     def find(conditions, key) #:doc:
0
       objs = []
0
+
0
       if conditions.is_a? Hash
0
- raise "Resource.find(Hash) expects a single key, value pair" \
0
- unless conditions.size == 1
0
- conds = conditions.to_a.flatten
0
- @@store.resources[key].each do |o|
0
- objs << o[1] if o[1].send(conds[0]) == conds[1]
0
+ unless conditions.to_a.flatten.map {|e| e.is_a? Query}.include?(true)
0
+ conds = conditions.to_a.flatten
0
+ @@store.resources[key].each do |o|
0
+ objs << o[1] if o[1].send(conds[0]) == conds[1]
0
+ end
0
+ else
0
+ parsed_conditions = parse_conditions(conditions)
0
+ @@store.resources[key].each do |o|
0
+ objs << o[1] if matches_conditions?(o[1], parsed_conditions)
0
+ end
0
         end
0
       else
0
- parsed_conditions = parse_conditions(conditions)
0
- @@store.resources[key].each do |o|
0
- objs << o[1] if matches_conditions?(o[1], parsed_conditions)
0
- end
0
+ raise "Resource.find expects a Hash, got a #{conditions.class}"
0
       end
0
       objs
0
     end
0
     
0
+ # Checks the list of fields for a given +klass+ to see if +field+
0
+ # is included
0
+ # === Parameters
0
+ # +field+:: The field to look for
0
+ # +klass+:: The class to look in
0
     def field_declared?(field,klass)
0
       @@fields[klass.to_s.make_key].each do |f|
0
         return true if f[:name] == field
0
@@ -381,43 +393,15 @@ module Stone
0
       eval(tf_ary.join)
0
     end
0
     
0
- # Accepts +conditions+ like
0
- # "name.include?('nick') && email == 'nick@bzzybee.com"
0
- # and turns them into an +ary+ of expressions and their conditionals
0
- # === Parameters
0
- # +conditions+:: The plain string conditions
0
- def parse_conditions(conditions) #:doc:
0
- ary = []
0
- # Facets breaks for some reason on single condition expressions
0
- # e.g. "name == 'Nick DeMonner'"
0
- # but not on multiple ones like
0
- # "name == 'Nick DeMonner' && blah.include?('blah')"
0
- begin
0
- expr = conditions.split(/\s+&{2}|\|{2}\s+/)
0
- rescue
0
- expr = [conditions]
0
- end
0
- op = conditions.scan(/&{2}|\|{2}/)
0
- expr.each_with_index do |e,i|
0
- ary << e.strip
0
- ary << op[i] if op[i]
0
- end
0
- # convert each expr into an obj.meth(arg) format
0
- # so that name == 'nick' becomes name.==('nick')
0
- ary.each_with_index do |e,i|
0
- if i % 2 == 0 && e.split.size != 1 && !e.match(/.+(.+)/)
0
- expr_ary = e.split
0
- expr_ary[0] = expr_ary[0] + "."
0
- expr_ary[1] = expr_ary[1] + "("
0
- if expr_ary.size % 2 == 0
0
- expr_ary[expr_ary.size-1] = " " + expr_ary[expr_ary.size-1] + ")"
0
- else
0
- expr_ary[expr_ary.size-1] = expr_ary[expr_ary.size-1] + ")"
0
- end
0
- ary[i] = expr_ary.join
0
- end
0
+ # Turns conditions into a set of expressions that can be evaluated
0
+ def parse_conditions(hash)
0
+ conds = []
0
+ hash.each do |k,v|
0
+ conds << k.expression_for(v)
0
+ conds << "&&"
0
       end
0
- ary
0
+ conds.pop
0
+ conds
0
     end
0
   end # Resource
0
   
...
69
70
71
72
 
73
74
75
76
 
 
77
78
79
80
81
 
 
82
83
 
84
85
86
87
88
89
90
91
92
93
 
94
95
96
...
99
100
101
102
 
103
104
105
106
 
107
108
109
110
111
112
113
 
114
115
116
...
131
132
133
134
 
135
136
137
...
141
142
143
144
 
145
146
147
...
69
70
71
 
72
73
74
 
 
75
76
77
78
79
 
 
80
81
82
 
83
84
85
86
 
 
 
 
 
87
 
88
89
90
91
...
94
95
96
 
97
98
99
100
 
101
102
103
104
105
106
107
 
108
109
110
111
...
126
127
128
 
129
130
131
132
...
136
137
138
 
139
140
141
142
0
@@ -69,28 +69,23 @@ describe Stone::Resource do
0
   
0
   it "should accept Resource.find(hash) form" do
0
     author = Author.first(:name => "Nick DeMonner")
0
- author.should be_instance_of Author
0
+ author.should be_instance_of(Author)
0
   end
0
   
0
- it "should raise an exception if more than one key, value pair are used in find" do
0
- lambda {Author.first(:name => "Nick DeMonner", :email => "nick@cladby.com")}.should raise_error
0
+ it "should raise an exception anything other than a Hash is provided for find" do
0
+ lambda {Author.first("Nick")}.should raise_error
0
   end
0
   
0
   it "should find and return all objects that match conditions provided" do
0
- @author.name = "Bob Hicklesby"
0
- @author.email = "bob@gmail.com"
0
+ @author.name = "Nick Hicklesby"
0
+ @author.email = "nick@gmail.com"
0
     @author.save
0
- people = Author.all("name == 'Nick DeMonner' || email.include?('gmail')")
0
+ people = Author.all(:name.includes => "Nick")
0
     people.size.should == 2
0
   end
0
   
0
- it "should accept cool methods for searching" do
0
- people = Author.all("name.include?('Nick DeMonner')")
0
- people.size.should == 1
0
- end
0
-
0
   it "should find and return the first object that matches conditions provided" do
0
- person = Author.first("name == 'Nick DeMonner'")
0
+ person = Author.first(:name.equals => 'Nick DeMonner')
0
     person.id.should == 1
0
   end
0
   
0
@@ -99,18 +94,18 @@ describe Stone::Resource do
0
     @author.email = "higglebear@higgly.com"
0
     @author.favorite_number = 3
0
     @author.save
0
- Author.first("favorite_number == 3").should be_instance_of(Author)
0
+ Author.first(:favorite_number.equals => 3).should be_instance_of(Author)
0
   end
0
   
0
   it "should perform a put if the object already exists on save" do
0
- author = Author.first("name == 'Nick DeMonner'")
0
+ author = Author.first(:name.equals => 'Nick DeMonner')
0
     author.email = "nick@bzzybee.com"
0
     author.save
0
     Author.get(author.id).email.should == "nick@bzzybee.com"
0
   end
0
   
0
   it "should delete an object and it's yaml file upon Resource.delete" do
0
- author = Author.first("favorite_number == 3")
0
+ author = Author.first(:favorite_number.equals => 3)
0
     Author.delete(author.id).should be_true
0
   end
0
   
0
@@ -131,7 +126,7 @@ describe Stone::Resource do
0
     @post = Post.new
0
     @post.title = "Stone is Cool"
0
     @post.body = "Stone is cool because..."
0
- author = Author.first("name == 'Nick DeMonner'")
0
+ author = Author.first(:name.equals => 'Nick DeMonner')
0
     @post.author_id = author.id
0
     @post.save
0
     @post.author.should be_instance_of(Author)
0
@@ -141,7 +136,7 @@ describe Stone::Resource do
0
     @post = Post.new
0
     @post.title = "Stone is Awesome"
0
     @post.body = "Stone is awesome because..."
0
- author = Author.first("name == 'Nick DeMonner'")
0
+ author = Author.first(:name.equals => 'Nick DeMonner')
0
     @post.author_id = author.id
0
     @post.save
0
     author.posts.size.should == 2
...
85
86
87
88
 
89
90
91
92
 
 
93
94
95
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
134
135
...
85
86
87
 
88
89
90
 
 
91
92
93
94
95
...
115
116
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
0
@@ -85,11 +85,11 @@ h3. Get, Post, Put, and Delete
0
   Author.first(:name => "Nick DeMonner")
0
   
0
   # brings back first author whose name contains "Nick"
0
- Author.first("name.include?('Nick')")
0
+ Author.first(:name.includes => 'Nick')
0
   
0
   # brings back all authors whose email contains "gmail.com", and who
0
- # were created before some_date_time
0
- Author.all("email.include?('gmail.com') && created_at < some_date_time")
0
+ # were created before today
0
+ Author.all(:email.includes => "gmail.com", :created_at.lt => DateTime.now)
0
 </pre>
0
 
0
 * Posting
0
@@ -115,21 +115,43 @@ h3. Get, Post, Put, and Delete
0
 
0
 h3. A Word About Finding Stuff
0
 
0
-You'll note that Stone uses a string containing ruby expressions to find
0
-your data. Any method works here, just be careful when inserting values.
0
-
0
-* This...
0
-<pre syntax="ruby">
0
- Author.first("name == #{name}")
0
-</pre>
0
-...won't work.
0
-
0
-* Instead, use this...
0
-<pre syntax="ruby">
0
- Author.first("name == '#{name}'")
0
-</pre>
0
-... and your luck will change.
0
-
0
+Stone uses a series of unique methods (à la DataMapper) to finding objects.
0
+You may use the following methods when searching:
0
+
0
+* <pre syntax="ruby">
0
+ # matches all objects whose <code>field</code> is greater
0
+ # than <code>thing</code>
0
+ :field.gt => thing
0
+ </pre>
0
+
0
+* <pre syntax="ruby">
0
+ # matches objects whose <code>field</code> is greater than
0
+ # or equal to <code>thing</code>
0
+ :field.gte => thing
0
+ </pre>
0
+
0
+* <pre syntax="ruby">
0
+ # matches all objects whose <code>field</code> is less
0
+ # than <code>thing</code>
0
+ :field.lt => thing
0
+ </pre>
0
+
0
+* <pre syntax="ruby">
0
+ # matches all objects whose <code>field</code> is less than
0
+ # or equal to <code>thing</code>
0
+ :field.lte => thing
0
+ </pre>
0
+
0
+* <pre syntax="ruby">
0
+ # matches all objects whose <code>field</code> contains <code>thing</code>
0
+ :field.includes => thing
0
+ </pre>
0
+
0
+* <pre syntax="ruby">
0
+ # matches objects whose <code>field</code> matches <code>pattern</code>
0
+ :field.matches => pattern # pattern is any RegEx
0
+ </pre>
0
+
0
 h2. License
0
 
0
 This code is free to use under the terms of the MIT license.
...
1
2
 
3
4
5
6
7
 
8
9
10
...
1
 
2
3
4
5
6
 
7
8
9
10
0
@@ -1,10 +1,10 @@
0
 --- !ruby/object:Author
0
-created_at: 2008-04-13T13:02:17-07:00
0
+created_at: 2008-04-13T16:02:30-07:00
0
 email: nick@cladby.com
0
 errors: !ruby/object:Validatable::Errors
0
   errors: {}
0
 
0
-favorite_number: 42
0
+favorite_number: 48
0
 id: 1
0
 name: Nick DeMonner
0
 times_validated_hash:
...
1
2
 
3
4
5
6
7
 
8
9
10
...
1
 
2
3
4
5
6
 
7
8
9
10
0
@@ -1,10 +1,10 @@
0
 --- !ruby/object:Author
0
-created_at: 2008-04-13T13:02:17-07:00
0
+created_at: 2008-04-13T16:02:30-07:00
0
 email: heyo@something.com
0
 errors: !ruby/object:Validatable::Errors
0
   errors: {}
0
 
0
-favorite_number: 4
0
+favorite_number: 22
0
 id: 2
0
 name: Mike McMichaels
0
 times_validated_hash:
...
1
2
 
3
4
5
6
7
 
8
9
10
...
1
 
2
3
4
5
6
 
7
8
9
10
0
@@ -1,10 +1,10 @@
0
 --- !ruby/object:Author
0
-created_at: 2008-04-13T13:02:17-07:00
0
+created_at: 2008-04-13T16:02:30-07:00
0
 email: weyo@something.com
0
 errors: !ruby/object:Validatable::Errors
0
   errors: {}
0
 
0
-favorite_number: 39
0
+favorite_number: 11
0
 id: 3
0
 name: Mary Poppins
0
 times_validated_hash:
...
1
2
3
 
 
4
5
6
7
 
8
9
 
10
11
12
...
1
 
 
2
3
4
5
6
 
7
8
 
9
10
11
12
0
@@ -1,12 +1,12 @@
0
 --- !ruby/object:Author
0
-created_at: 2008-04-13T13:02:17-07:00
0
-email: bob@gmail.com
0
+created_at: 2008-04-13T16:02:30-07:00
0
+email: nick@gmail.com
0
 errors: !ruby/object:Validatable::Errors
0
   errors: {}
0
 
0
-favorite_number: 13
0
+favorite_number: 22
0
 id: 4
0
-name: Bob Hicklesby
0
+name: Nick Hicklesby
0
 times_validated_hash:
0
   Author/Validatable::ValidatesPresenceOf/email: 1
0
   Author/Validatable::ValidatesPresenceOf/name: 1
...
1
2
 
3
4
5
6
7
 
8
9
10
...
1
 
2
3
4
5
6
 
7
8
9
10
0
@@ -1,10 +1,10 @@
0
 --- !ruby/object:Author
0
-created_at: 2008-04-13T13:02:17-07:00
0
+created_at: 2008-04-13T16:02:30-07:00
0
 email: chariot_guy@hotmail.com
0
 errors: !ruby/object:Validatable::Errors
0
   errors: {}
0
 
0
-favorite_number: 11
0
+favorite_number: 23
0
 id: 5
0
 name: Ben Hurr
0
 times_validated_hash:
...
69
70
71
72
 
73
74
75
76
 
 
77
78
79
80
81
 
 
82
83
 
84
85
86
87
88
89
90
91
92
93
 
94
95
96
...
99
100
101
102
 
103
104
105
106
 
107
108
109
110
111
112
113
 
114
115
116
...
131
132
133
134
 
135
136
137
...
141
142
143
144
 
145
146
147
...
69
70
71
 
72
73
74
 
 
75
76
77
78
79
 
 
80
81
82
 
83
84
85
86
 
 
 
 
 
87
 
88
89
90
91
...
94
95
96
 
97
98
99
100
 
101
102
103
104
105
106
107
 
108
109
110
111
...
126
127
128
 
129
130
131
132
...
136
137
138
 
139
140
141
142
0
@@ -69,28 +69,23 @@ describe Stone::Resource do
0
   
0
   it "should accept Resource.find(hash) form" do
0
     author = Author.first(:name => "Nick DeMonner")
0
- author.should be_instance_of Author
0
+ author.should be_instance_of(Author)
0
   end
0
   
0
- it "should raise an exception if more than one key, value pair are used in find" do
0
- lambda {Author.first(:name => "Nick DeMonner", :email => "nick@cladby.com")}.should raise_error
0
+ it "should raise an exception anything other than a Hash is provided for find" do
0
+ lambda {Author.first("Nick")}.should raise_error
0
   end
0
   
0
   it "should find and return all objects that match conditions provided" do
0
- @author.name = "Bob Hicklesby"
0
- @author.email = "bob@gmail.com"
0
+ @author.name = "Nick Hicklesby"
0
+ @author.email = "nick@gmail.com"
0
     @author.save
0
- people = Author.all("name == 'Nick DeMonner' || email.include?('gmail')")
0
+ people = Author.all(:name.includes => "Nick")
0
     people.size.should == 2
0
   end
0
   
0
- it "should accept cool methods for searching" do
0
- people = Author.all("name.include?('Nick DeMonner')")
0
- people.size.should == 1
0
- end
0
-
0
   it "should find and return the first object that matches conditions provided" do
0
- person = Author.first("name == 'Nick DeMonner'")
0
+ person = Author.first(:name.equals => 'Nick DeMonner')
0
     person.id.should == 1
0
   end
0
   
0
@@ -99,18 +94,18 @@ describe Stone::Resource do
0
     @author.email = "higglebear@higgly.com"
0
     @author.favorite_number = 3
0
     @author.save
0
- Author.first("favorite_number == 3").should be_instance_of(Author)
0
+ Author.first(:favorite_number.equals => 3).should be_instance_of(Author)
0
   end
0
   
0
   it "should perform a put if the object already exists on save" do
0
- author = Author.first("name == 'Nick DeMonner'")
0
+ author = Author.first(:name.equals => 'Nick DeMonner')
0
     author.email = "nick@bzzybee.com"
0
     author.save
0
     Author.get(author.id).email.should == "nick@bzzybee.com"
0
   end
0
   
0
   it "should delete an object and it's yaml file upon Resource.delete" do
0
- author = Author.first("favorite_number == 3")
0
+ author = Author.first(:favorite_number.equals => 3)
0
     Author.delete(author.id).should be_true
0
   end
0
   
0
@@ -131,7 +126,7 @@ describe Stone::Resource do
0
     @post = Post.new
0
     @post.title = "Stone is Cool"
0
     @post.body = "Stone is cool because..."
0
- author = Author.first("name == 'Nick DeMonner'")
0
+ author = Author.first(:name.equals => 'Nick DeMonner')
0
     @post.author_id = author.id
0
     @post.save
0
     @post.author.should be_instance_of(Author)
0
@@ -141,7 +136,7 @@ describe S