public
Fork of ndemonner/stone
Description: Plug-and-play data persistence created for small Ruby web applications.
Homepage: http://stone.rubyforge.org
Clone URL: git://github.com/juretta/stone.git
Working with Merb.

* Fixed a bunch of bugs prohibiting a working Merb relationship
* Implemented hash-based Resource.update_attributes
* Implemented hash-based Resource.find
ndemonner (author)
Sun Apr 13 14:35:50 -0700 2008
commit  d6b1774244f972ac97d89249cf29e2829e867d5b
tree    190d0aeae2b2b48422ecc40112632b5b325a91ec
parent  6cc6aace7493d0a7eb0e63f5fa15ffc52605b72c
...
8
9
10
11
 
12
13
 
14
15
16
...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
40
41
42
...
57
58
59
60
 
61
62
63
64
65
66
67
68
69
70
71
 
72
73
74
...
8
9
10
 
11
12
 
13
14
15
16
...
20
21
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24
25
26
...
41
42
43
 
44
45
46
47
48
 
 
 
 
 
 
 
49
50
51
52
0
@@ -8,9 +8,9 @@ def usage
0
   puts <<-EOS
0
   
0
   
0
- stone-gen [model:merb|model:rails] ModelName field:type field:type ...
0
+ stone-gen model ModelName field:type field:type ...
0
 
0
- e.g. stone-gen model:merb Author name:string street_number:fixnum
0
+ e.g. stone-gen model Author name:string street_number:fixnum
0
 
0
     Works just like all the other model generators out there,
0
     just remember that Stone only accepts Ruby primitives for
0
@@ -20,23 +20,7 @@ def usage
0
   EOS
0
 end
0
 
0
-def gen_rails_model(args)
0
- model_name = args.first.camelcase
0
- file_name = model_name.snakecase
0
- args.shift
0
- fields = Hash[*(args.map{|a| a.split(":") }.flatten)]
0
- model_str = "class #{model_name}\n include Stone::Resource\n\n"
0
- for field in fields
0
- model_str << " field :#{field.first}, #{field.last.capitalize}\n"
0
- end
0
- model_str << "end"
0
- File.open(File.join(Dir.pwd, "app/models/#{file_name}.rb"), "w") do |file|
0
- file << model_str
0
- end
0
- puts "Model: #{model_name} created."
0
-end
0
-
0
-def gen_merb_model(args)
0
+def gen_model(args)
0
   model_name = args.first.camelcase
0
   file_name = model_name.snakecase
0
   args.shift
0
@@ -57,18 +41,12 @@ if ARGV.empty?
0
 else
0
   args = ARGV
0
   case args.first
0
- when "model:rails"
0
+ when "model"
0
     args.shift
0
     if args.empty?
0
       usage
0
     else
0
- gen_rails_model(args)
0
- end
0
- when "model:merb"
0
- if args.empty?
0
- usage
0
- else
0
- gen_rails_model(args)
0
+ gen_model(args)
0
     end
0
   else
0
     usage
...
17
18
19
20
21
22
23
24
...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
60
61
62
63
64
65
 
 
 
66
67
 
68
69
70
 
 
71
72
73
...
17
18
19
 
 
20
21
22
...
37
38
39
 
 
 
 
 
 
 
 
 
40
41
42
...
49
50
51
 
 
 
52
53
54
55
 
56
57
 
 
58
59
60
61
62
0
@@ -17,8 +17,6 @@ STONE_ROOT = Dir.pwd
0
 module Stone
0
   class << self
0
     
0
- @@dir ||= ""
0
-
0
     # See Stone::Utilities.backup
0
     def backup(from_path, to_path = nil)
0
       Stone::Utilities.backup(from_path, to_path)
0
@@ -39,15 +37,6 @@ module Stone
0
       Stone::Utilities.metrics_for(path)
0
     end
0
     
0
- def local_dir=(value) #:nodoc:
0
- @@dir = value
0
- end
0
-
0
- # Provides the directory path to the local (app-specific) datastore
0
- def local_dir
0
- @@dir
0
- end
0
-
0
     # For spec stuff only
0
     def empty_datastore
0
       if File.exists? STONE_ROOT/"sandbox_for_specs/datastore"
0
@@ -60,14 +49,14 @@ module Stone
0
     # +path+<String>::
0
     # Path to create or update datastore (usually an application's root)
0
     # +resources+<Array>:: A list of resources that exist for the application
0
- def start(path, resources)
0
- self.local_dir = path/"datastore#{}"
0
- FileUtils.mkdir(self.local_dir) unless File.exists?(self.local_dir)
0
+ def start(path, resources, framework = nil)
0
+ DataStore.local_dir = path/"datastore"
0
+ FileUtils.mkdir(DataStore.local_dir) unless File.exists?(DataStore.local_dir)
0
       resources.each do |resource|
0
- require resource
0
+ require resource unless framework == :merb || framework == :rails
0
         name = File.basename(resource).gsub(".rb", "").pluralize
0
- unless File.exists? self.local_dir/name
0
- FileUtils.mkdir(self.local_dir/name)
0
+ unless File.exists? DataStore.local_dir/name
0
+ FileUtils.mkdir(DataStore.local_dir/name)
0
         end
0
       end
0
     end
...
3
4
5
 
 
 
 
 
 
 
 
 
 
 
6
7
8
9
10
11
 
12
13
14
...
38
39
40
41
 
42
43
44
...
50
51
52
53
 
54
55
 
56
57
58
...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
22
23
24
25
...
49
50
51
 
52
53
54
55
...
61
62
63
 
64
65
 
66
67
68
69
0
@@ -3,12 +3,23 @@ module Stone
0
   class DataStore
0
     
0
     class << self
0
+ @dir ||= ""
0
+
0
+ def local_dir=(value) #:nodoc:
0
+ @dir = value
0
+ end
0
+
0
+ # Provides the directory path to the local (app-specific) datastore
0
+ def local_dir
0
+ @dir || Dir.pwd/"datastore"
0
+ end
0
+
0
       # Loads yaml files specific to the resource represented by +sym+
0
       # === Parameters
0
       # +sym+::
0
       # Symbol representing resource data to load
0
       def load_data(sym)
0
- dir = Stone.local_dir
0
+ dir = self.local_dir
0
         ymls = Dir.glob(dir/sym.to_s.pluralize/"*.yml")
0
         objs = []
0
         unless ymls.empty?
0
@@ -38,7 +49,7 @@ module Stone
0
       # === Parameters
0
       # +obj+:: The object to be persisted
0
       def write_yaml(obj)
0
- path = Stone.local_dir/obj.class.to_s.downcase.pluralize/"#{obj.id}.yml"
0
+ path = self.local_dir/obj.class.to_s.downcase.pluralize/"#{obj.id}.yml"
0
         File.open(path, 'w') do |out|
0
           YAML.dump(obj, out)
0
         end
0
@@ -50,9 +61,9 @@ module Stone
0
       # +klass_dir+:: directory in which object resides
0
       def delete(id, klass_dir)
0
         raise "Object could not be found" \
0
- unless File.exists?(Stone.local_dir/klass_dir/"#{id}.yml")
0
+ unless File.exists?(self.local_dir/klass_dir/"#{id}.yml")
0
             
0
- FileUtils.remove_file(Stone.local_dir/klass_dir/"#{id}.yml")
0
+ FileUtils.remove_file(self.local_dir/klass_dir/"#{id}.yml")
0
         true
0
       end
0
     end # self
...
13
14
15
 
 
 
 
 
 
 
16
17
18
19
20
21
 
22
 
 
 
 
 
 
 
 
 
 
 
23
24
25
26
27
28
29
30
31
32
 
33
34
35
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
245
246
247
 
 
 
 
 
 
 
 
 
 
 
 
 
248
249
250
...
257
258
259
260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
262
263
...
302
303
304
305
306
307
 
 
 
 
 
 
 
 
 
 
 
 
308
309
310
...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
 
 
 
 
 
45
46
47
48
...
162
163
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
166
167
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
258
259
260
 
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
332
333
334
 
 
 
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
0
@@ -13,23 +13,36 @@ module Stone
0
     
0
     class << self
0
       def included(base)
0
+ rsrc_sym = base.to_s.make_key
0
+
0
+ @@callbacks ||= Callbacks.new
0
+ @@callbacks.register_klass(base)
0
+
0
+ @@store ||= DataStore.new
0
+
0
         base.send(:extend, self)
0
         base.send(:include, ::Validatable)
0
         
0
         unless base.to_s.downcase == "spec::example::examplegroup::subclass_1"
0
           base.class_eval <<-EOS, __FILE__, __LINE__
0
- def initialize
0
+ def initialize(hash = nil)
0
               self.id = self.next_id_for_klass(self.class)
0
+ unless hash.blank?
0
+ hash.each_key do |k|
0
+ if hash[k].is_a? Hash
0
+ hash[k].each do |k,v|
0
+ self.send(k.to_s+"=",v)
0
+ end
0
+ else
0
+ self.send(k.to_s+"=", hash[k])
0
+ end
0
+ end
0
+ end
0
             end
0
           EOS
0
         end
0
         
0
- rsrc_sym = base.to_s.make_key
0
- @@callbacks ||= Callbacks.new
0
- @@callbacks.register_klass(base)
0
-
0
- @@store ||= DataStore.new
0
- unless @@store.resources.include? rsrc_sym
0
+ unless @@store.resources.include?(rsrc_sym)
0
           @@store.resources[rsrc_sym] = DataStore.load_data(rsrc_sym)
0
         end
0
       end
0
@@ -149,31 +162,6 @@ module Stone
0
     def has_and_belongs_to_many(resource, *args)
0
     end
0
     
0
- # Save an object to the current DataStore instance.
0
- def save
0
- return false unless self.fields_are_valid?
0
- fire(:before_save)
0
- return false unless self.valid?
0
- sym = DataStore.determine_save_method(self, @@store)
0
- self.class.send(sym, self)
0
- fire(:after_save)
0
- end
0
-
0
- # Determines whether the field classes of a given object match the field
0
- # class declarations
0
- def fields_are_valid?
0
- klass_sym = self.class.to_s.make_key
0
- @@fields[klass_sym].each do |field|
0
- unless self.send(field[:name]).class == field[:klass] || self.send(field[:name]) == nil
0
- return false
0
- end
0
- if field[:unique] == true
0
- return false if self.class.first("#{field[:name]} == '#{self.send(field[:name])}'")
0
- end
0
- end
0
- true
0
- end
0
-
0
     # Returns the first object matching +conditions+, or the first object
0
     # if no conditions are specified
0
     # === Parameters
0
@@ -245,6 +233,19 @@ module Stone
0
       false
0
     end
0
     
0
+ def update_attributes(hash)
0
+ hash.each_key do |k|
0
+ if hash[k].is_a? Hash
0
+ hash[k].each do |k,v|
0
+ self.send(k.to_s+"=",v)
0
+ end
0
+ else
0
+ self.send(k.to_s+"=", hash[k])
0
+ end
0
+ end
0
+ self.save
0
+ end
0
+
0
     # Determine the next id number to use based on the last stored object's id
0
     # of class +klass+
0
     # === Parameters
0
@@ -257,7 +258,36 @@ module Stone
0
         return 1
0
       end
0
     end
0
-
0
+
0
+ # Save an object to the current DataStore instance.
0
+ def save
0
+ return false unless self.fields_are_valid?
0
+ fire(:before_save)
0
+ return false unless self.valid?
0
+ sym = DataStore.determine_save_method(self, @@store)
0
+ self.class.send(sym, self)
0
+ fire(:after_save)
0
+ end
0
+
0
+ # Determines whether the field classes of a given object match the field
0
+ # class declarations
0
+ def fields_are_valid?
0
+ klass_sym = self.class.to_s.make_key
0
+ @@fields[klass_sym].each do |field|
0
+ unless self.send(field[:name]).class == field[:klass] || self.send(field[:name]) == nil || self.already_exists?
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
+ end
0
+ end
0
+ true
0
+ end
0
+
0
+ def already_exists?
0
+ DataStore.determine_save_method(self, @@store) == :put
0
+ end
0
+
0
     private
0
     
0
     # Fires the given callback in the current instance of Callbacks
0
@@ -302,9 +332,18 @@ module Stone
0
     # DataStore instance
0
     def find(conditions, key) #:doc:
0
       objs = []
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
+ 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
+ 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
       objs
0
     end
...
8
9
10
11
 
12
13
 
14
15
16
...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
40
41
42
...
57
58
59
60
 
61
62
63
64
65
66
67
68
69
70
71
 
72
73
74
...
8
9
10
 
11
12
 
13
14
15
16
...
20
21
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
24
25
26
...
41
42
43
 
44
45
46
47
48
 
 
 
 
 
 
 
49
50
51
52
0
@@ -8,9 +8,9 @@ def usage
0
   puts <<-EOS
0
   
0
   
0
- stone-gen [model:merb|model:rails] ModelName field:type field:type ...
0
+ stone-gen model ModelName field:type field:type ...
0
 
0
- e.g. stone-gen model:merb Author name:string street_number:fixnum
0
+ e.g. stone-gen model Author name:string street_number:fixnum
0
 
0
     Works just like all the other model generators out there,
0
     just remember that Stone only accepts Ruby primitives for
0
@@ -20,23 +20,7 @@ def usage
0
   EOS
0
 end
0
 
0
-def gen_rails_model(args)
0
- model_name = args.first.camelcase
0
- file_name = model_name.snakecase
0
- args.shift
0
- fields = Hash[*(args.map{|a| a.split(":") }.flatten)]
0
- model_str = "class #{model_name}\n include Stone::Resource\n\n"
0
- for field in fields
0
- model_str << " field :#{field.first}, #{field.last.capitalize}\n"
0
- end
0
- model_str << "end"
0
- File.open(File.join(Dir.pwd, "app/models/#{file_name}.rb"), "w") do |file|
0
- file << model_str
0
- end
0
- puts "Model: #{model_name} created."
0
-end
0
-
0
-def gen_merb_model(args)
0
+def gen_model(args)
0
   model_name = args.first.camelcase
0
   file_name = model_name.snakecase
0
   args.shift
0
@@ -57,18 +41,12 @@ if ARGV.empty?
0
 else
0
   args = ARGV
0
   case args.first
0
- when "model:rails"
0
+ when "model"
0
     args.shift
0
     if args.empty?
0
       usage
0
     else
0
- gen_rails_model(args)
0
- end
0
- when "model:merb"
0
- if args.empty?
0
- usage
0
- else
0
- gen_rails_model(args)
0
+ gen_model(args)
0
     end
0
   else
0
     usage
...
17
18
19
20
21
22
23
24
...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
60
61
62
63
64
65
 
 
 
66
67
 
68
69
70
 
 
71
72
73
...
17
18
19
 
 
20
21
22
...
37
38
39
 
 
 
 
 
 
 
 
 
40
41
42
...
49
50
51
 
 
 
52
53
54
55
 
56
57
 
 
58
59
60
61
62
0
@@ -17,8 +17,6 @@ STONE_ROOT = Dir.pwd
0
 module Stone
0
   class << self
0
     
0
- @@dir ||= ""
0
-
0
     # See Stone::Utilities.backup
0
     def backup(from_path, to_path = nil)
0
       Stone::Utilities.backup(from_path, to_path)
0
@@ -39,15 +37,6 @@ module Stone
0
       Stone::Utilities.metrics_for(path)
0
     end
0
     
0
- def local_dir=(value) #:nodoc:
0
- @@dir = value
0
- end
0
-
0
- # Provides the directory path to the local (app-specific) datastore
0
- def local_dir
0
- @@dir
0
- end
0
-
0
     # For spec stuff only
0
     def empty_datastore
0
       if File.exists? STONE_ROOT/"sandbox_for_specs/datastore"
0
@@ -60,14 +49,14 @@ module Stone
0
     # +path+<String>::
0
     # Path to create or update datastore (usually an application's root)
0
     # +resources+<Array>:: A list of resources that exist for the application
0
- def start(path, resources)
0
- self.local_dir = path/"datastore#{}"
0
- FileUtils.mkdir(self.local_dir) unless File.exists?(self.local_dir)
0
+ def start(path, resources, framework = nil)
0
+ DataStore.local_dir = path/"datastore"
0
+ FileUtils.mkdir(DataStore.local_dir) unless File.exists?(DataStore.local_dir)
0
       resources.each do |resource|
0
- require resource
0
+ require resource unless framework == :merb || framework == :rails
0
         name = File.basename(resource).gsub(".rb", "").pluralize
0
- unless File.exists? self.local_dir/name
0
- FileUtils.mkdir(self.local_dir/name)
0
+ unless File.exists? DataStore.local_dir/name
0
+ FileUtils.mkdir(DataStore.local_dir/name)
0
         end
0
       end
0
     end
...
3
4
5
 
 
 
 
 
 
 
 
 
 
 
6
7
8
9
10
11
 
12
13
14
...
38
39
40
41
 
42
43
44
...
50
51
52
53
 
54
55
 
56
57
58
...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
22
23
24
25
...
49
50
51
 
52
53
54
55
...
61
62
63
 
64
65
 
66
67
68
69
0
@@ -3,12 +3,23 @@ module Stone
0
   class DataStore
0
     
0
     class << self
0
+ @dir ||= ""
0
+
0
+ def local_dir=(value) #:nodoc:
0
+ @dir = value
0
+ end
0
+
0
+ # Provides the directory path to the local (app-specific) datastore
0
+ def local_dir
0
+ @dir || Dir.pwd/"datastore"
0
+ end
0
+
0
       # Loads yaml files specific to the resource represented by +sym+
0
       # === Parameters
0
       # +sym+::
0
       # Symbol representing resource data to load
0
       def load_data(sym)
0
- dir = Stone.local_dir
0
+ dir = self.local_dir
0
         ymls = Dir.glob(dir/sym.to_s.pluralize/"*.yml")
0
         objs = []
0
         unless ymls.empty?
0
@@ -38,7 +49,7 @@ module Stone
0
       # === Parameters
0
       # +obj+:: The object to be persisted
0
       def write_yaml(obj)
0
- path = Stone.local_dir/obj.class.to_s.downcase.pluralize/"#{obj.id}.yml"
0
+ path = self.local_dir/obj.class.to_s.downcase.pluralize/"#{obj.id}.yml"
0
         File.open(path, 'w') do |out|
0
           YAML.dump(obj, out)
0
         end
0
@@ -50,9 +61,9 @@ module Stone
0
       # +klass_dir+:: directory in which object resides
0
       def delete(id, klass_dir)
0
         raise "Object could not be found" \
0
- unless File.exists?(Stone.local_dir/klass_dir/"#{id}.yml")
0
+ unless File.exists?(self.local_dir/klass_dir/"#{id}.yml")
0
             
0
- FileUtils.remove_file(Stone.local_dir/klass_dir/"#{id}.yml")
0
+ FileUtils.remove_file(self.local_dir/klass_dir/"#{id}.yml")
0
         true
0
       end
0
     end # self
...
13
14
15
 
 
 
 
 
 
 
16
17
18
19
20
21
 
22
 
 
 
 
 
 
 
 
 
 
 
23
24
25
26
27
28
29
30
31
32
 
33
34
35
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
245
246
247
 
 
 
 
 
 
 
 
 
 
 
 
 
248
249
250
...
257
258
259
260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
262
263
...
302
303
304
305
306
307
 
 
 
 
 
 
 
 
 
 
 
 
308
309
310
...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
 
 
 
 
 
45
46
47
48
...
162
163
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
166
167
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
258
259
260
 
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
332
333
334
 
 
 
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
0
@@ -13,23 +13,36 @@ module Stone
0
     
0
     class << self
0
       def included(base)
0
+ rsrc_sym = base.to_s.make_key
0
+
0
+ @@callbacks ||= Callbacks.new
0
+ @@callbacks.register_klass(base)
0
+
0
+ @@store ||= DataStore.new
0
+
0
         base.send(:extend, self)
0
         base.send(:include, ::Validatable)
0
         
0
         unless base.to_s.downcase == "spec::example::examplegroup::subclass_1"
0
           base.class_eval <<-EOS, __FILE__, __LINE__
0
- def initialize
0
+ def initialize(hash = nil)
0
               self.id = self.next_id_for_klass(self.class)
0
+ unless hash.blank?
0
+ hash.each_key do |k|
0
+ if hash[k].is_a? Hash
0
+ hash[k].each do |k,v|
0
+ self.send(k.to_s+"=",v)
0
+ end
0
+ else
0
+ self.send(k.to_s+"=", hash[k])
0
+ end
0
+ end
0
+ end
0
             end
0
           EOS
0
         end
0
         
0
- rsrc_sym = base.to_s.make_key
0
- @@callbacks ||= Callbacks.new
0
- @@callbacks.register_klass(base)
0
-
0
- @@store ||= DataStore.new
0
- unless @@store.resources.include? rsrc_sym
0
+ unless @@store.resources.include?(rsrc_sym)
0
           @@store.resources[rsrc_sym] = DataStore.load_data(rsrc_sym)
0
         end
0
       end
0
@@ -149,31 +162,6 @@ module Stone
0
     def has_and_belongs_to_many(resource, *args)
0
     end
0
     
0
- # Save an object to the current DataStore instance.
0
- def save
0
- return false unless self.fields_are_valid?
0
- fire(:before_save)
0
- return false unless self.valid?
0
- sym = DataStore.determine_save_method(self, @@store)
0
- self.class.send(sym, self)
0
- fire(:after_save)
0
- end
0
-
0
- # Determines whether the field classes of a given object match the field
0
- # class declarations
0
- def fields_are_valid?
0
- klass_sym = self.class.to_s.make_key
0
- @@fields[klass_sym].each do |field|
0
- unless self.send(field[:name]).class == field[:klass] || self.send(field[:name]) == nil
0
- return false
0
- end
0
- if field[:unique] == true
0
- return false if self.class.first("#{field[:name]} == '#{self.send(field[:name])}'")
0
- end
0
- end
0
- true
0
- end
0
-
0
     # Returns the first object matching +conditions+, or the first object
0
     # if no conditions are specified
0
     # === Parameters
0
@@ -245,6 +233,19 @@ module Stone
0
       false
0
     end
0
     
0
+ def update_attributes(hash)
0
+ hash.each_key do |k|
0
+ if hash[k].is_a? Hash
0
+ hash[k].each do |k,v|
0
+ self.send(k.to_s+"=",v)
0
+ end
0
+ else
0
+ self.send(k.to_s+"=", hash[k])
0
+ end
0
+ end
0
+ self.save
0
+ end
0
+
0
     # Determine the next id number to use based on the last stored object's id
0
     # of class +klass+
0
     # === Parameters
0
@@ -257,7 +258,36 @@ module Stone
0
         return 1
0
       end
0
     end
0
-
0
+
0
+ # Save an object to the current DataStore instance.
0
+ def save
0
+ return false unless self.fields_are_valid?
0
+ fire(:before_save)
0
+ return false unless self.valid?
0
+ sym = DataStore.determine_save_method(self, @@store)
0
+ self.class.send(sym, self)
0
+ fire(:after_save)
0
+ end
0
+
0
+ # Determines whether the field classes of a given object match the field
0
+ # class declarations
0
+ def fields_are_valid?
0
+ klass_sym = self.class.to_s.make_key
0
+ @@fields[klass_sym].each do |field|
0
+ unless self.send(field[:name]).class == field[:klass] || self.send(field[:name]) == nil || self.already_exists?
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
+ end
0
+ end
0
+ true
0
+ end
0
+
0
+ def already_exists?
0
+ DataStore.determine_save_method(self, @@store) == :put
0
+ end
0
+
0
     private
0
     
0
     # Fires the given callback in the current instance of Callbacks
0
@@ -302,9 +332,18 @@ module Stone
0
     # DataStore instance
0
     def find(conditions, key) #:doc:
0
       objs = []
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
+ 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
+ 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
       objs
0
     end