simple_record 1.1.24 → 1.1.26

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -113,12 +113,11 @@ To set a global prefix across all your models, use:
113
113
 
114
114
  ### Connection Modes
115
115
 
116
- There are 4 different connection modes:
116
+ There are 3 different connection modes:
117
117
 
118
118
  * per_request (default) - opens and closes a new connection to simpledb for every simpledb request. Not the best performance, but it's safe and can handle many concurrent requests at the same time (unlike single mode).
119
119
  * single - one connection across the entire application, not recommended unless the app is used by a single person.
120
120
  * per_thread - a connection is used for every thread in the application. This is good, but the catch is that you have to ensure to close the connection.
121
- * pool - NOT IMPLEMENTED YET - opens a maximum number of connections and round robins them for any simpledb request.
122
121
 
123
122
  You set the mode when you call establish_connection:
124
123
 
@@ -194,6 +193,12 @@ or
194
193
 
195
194
  o.something_id = x
196
195
 
196
+ #### Batch Save
197
+
198
+ To do a batch save using SimpleDB's batch saving feature to improve performance, simply create your objects, add them to an array, then call:
199
+
200
+ MyClass.batch_save(object_list)
201
+
197
202
  ## Kudos
198
203
 
199
204
  Special thanks to Garrett Cox for creating Activerecord2sdb which SimpleRecord is based on:
data/lib/simple_record.rb CHANGED
@@ -83,25 +83,19 @@ module SimpleRecord
83
83
  def initialize(attrs={})
84
84
  # todo: Need to deal with objects passed in. iterate through belongs_to perhaps and if in attrs, set the objects id rather than the object itself
85
85
 
86
- # if params[0]
87
- #we have to handle the virtuals. Right now, this assumes that all parameters are passed from inside an array
88
- #this is the usually the case when the parameters are passed passed via POST and obtained from the params array
89
- @@virtuals.each do |virtual|
90
- #we first copy the information for the virtual to an instance variable of the same name
91
- eval("@#{virtual}=params[0]['#{virtual}']")
92
- #and then remove the parameter before it is passed to initialize, so that it is NOT sent to SimpleDB
93
- eval("params[0].delete('#{virtual}')")
94
- end
95
- # super(*params)
96
- # else
97
- super
98
- # end
86
+ #we have to handle the virtuals.
87
+ @@virtuals.each do |virtual|
88
+ #we first copy the information for the virtual to an instance variable of the same name
89
+ eval("@#{virtual}=attrs['#{virtual}']")
90
+ #and then remove the parameter before it is passed to initialize, so that it is NOT sent to SimpleDB
91
+ eval("attrs.delete('#{virtual}')")
92
+ end
93
+ super
99
94
  @errors=SimpleRecord_errors.new
100
95
  @dirty = {}
101
96
  end
102
97
 
103
98
 
104
-
105
99
  # todo: move into Callbacks module
106
100
  #this bit of code creates a "run_blank" function for everything value in the @@callbacks array.
107
101
  #this function can then be inserted in the appropriate place in the save, new, destroy, etc overrides
@@ -509,7 +503,7 @@ module SimpleRecord
509
503
  end
510
504
 
511
505
  def set_updated
512
- # puts 'SETTING UPDATED'
506
+ #puts 'SETTING UPDATED'
513
507
  # @updated = DateTime.now
514
508
  self[:updated] = DateTime.now
515
509
  # @tester = 'some test value updated'
@@ -520,7 +514,7 @@ module SimpleRecord
520
514
  @@padding = 20
521
515
  @@date_format = "%Y-%m-%dT%H:%M:%S"; # Time to second precision
522
516
 
523
- def self.pad_and_offset(x)
517
+ def self.pad_and_offset(x) # Change name to something more appropriate like ruby_to_sdb
524
518
  # todo: add Float, etc
525
519
  # puts 'padding=' + x.class.name + " -- " + x.inspect
526
520
  if x.kind_of? Integer
@@ -536,7 +530,9 @@ module SimpleRecord
536
530
  # Amazon suggests: 2008-02-10T16:52:01.000-05:00
537
531
  # "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
538
532
  #
539
- if x.is_a? DateTime
533
+ if x.is_a? Date
534
+ x_str = x.strftime(@@date_format)
535
+ elsif x.is_a? DateTime
540
536
  x_str = x.new_offset(0).strftime(@@date_format)
541
537
  else
542
538
  x_str = x.getutc.strftime(@@date_format)
@@ -613,7 +609,7 @@ module SimpleRecord
613
609
  options[:dirty_atts] = @dirty
614
610
  end
615
611
  to_delete = get_atts_to_delete # todo: this should use the @dirty hash now
616
- # puts 'saving'
612
+ # puts 'done to_delete ' + to_delete.inspect
617
613
  if super(options)
618
614
  # puts 'SAVED super'
619
615
  self.class.cache_results(self)
@@ -646,6 +642,14 @@ module SimpleRecord
646
642
  end
647
643
  end
648
644
 
645
+ def save_with_validation!(options={})
646
+ if valid?
647
+ save
648
+ else
649
+ raise RecordInvalid.new(self)
650
+ end
651
+ end
652
+
649
653
  def pad_and_offset_ints_to_sdb()
650
654
 
651
655
  defined_attributes_local.each_pair do |name, att_meta|
@@ -687,7 +691,8 @@ module SimpleRecord
687
691
  ok = run_before_validation && (is_create ? run_before_validation_on_create : run_before_validation_on_update)
688
692
  return false unless ok
689
693
 
690
- validate
694
+ validate()
695
+
691
696
  is_create ? validate_on_create : validate_on_update
692
697
  # puts 'AFTER VALIDATIONS, ERRORS=' + errors.inspect
693
698
  if (!@errors.nil? && @errors.length > 0 )
@@ -730,9 +735,10 @@ module SimpleRecord
730
735
  # todo: this should use the @dirty hash now
731
736
  to_delete = []
732
737
  @attributes.each do |key, value|
733
- # puts 'value=' + value.inspect
734
- if value.nil? || (value.is_a?(Array) && value.size == 0)
738
+ # puts 'key=' + key.inspect + ' value=' + value.inspect
739
+ if value.nil? || (value.is_a?(Array) && value.size == 0) || (value.is_a?(Array) && value.size == 1 && value[0] == nil)
735
740
  to_delete << key
741
+ @attributes.delete(key)
736
742
  end
737
743
  end
738
744
  return to_delete
@@ -770,6 +776,7 @@ module SimpleRecord
770
776
  end
771
777
 
772
778
  def delete_niled(to_delete)
779
+ # puts 'to_delete=' + to_delete.inspect
773
780
  if to_delete.size > 0
774
781
  # puts 'Deleting attributes=' + to_delete.inspect
775
782
  delete_attributes to_delete
@@ -1131,5 +1138,17 @@ module SimpleRecord
1131
1138
  end
1132
1139
 
1133
1140
  end
1141
+
1142
+ class SimpleRecordError < StandardError
1143
+
1144
+ end
1145
+
1146
+ class RecordInvalid < SimpleRecordError
1147
+ attr_accessor :record
1148
+
1149
+ def initialize(record)
1150
+ @record = record
1151
+ end
1152
+ end
1134
1153
  end
1135
1154
 
data/lib/stats.rb CHANGED
@@ -1,16 +1,16 @@
1
- module SimpleRecord
2
- class Stats
3
- attr_accessor :selects, :puts
4
-
5
- def initialize
6
- @selects = 0
7
- @puts = 0
8
- end
9
-
10
- def clear
11
- self.selects = 0
12
- self.puts = 0
13
- end
14
- end
15
- end
16
-
1
+ module SimpleRecord
2
+ class Stats
3
+ attr_accessor :selects, :puts
4
+
5
+ def initialize
6
+ @selects = 0
7
+ @puts = 0
8
+ end
9
+
10
+ def clear
11
+ self.selects = 0
12
+ self.puts = 0
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,14 @@
1
+
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
4
+ require "yaml"
5
+ require 'right_aws'
6
+ require 'my_model'
7
+ require 'my_child_model'
8
+
9
+ x = 0
10
+ puts SimpleRecord::Base.pad_and_offset(x)
11
+
12
+ x = 1
13
+ puts SimpleRecord::Base.pad_and_offset(x)
14
+
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
2
+
3
+ class MyBaseModel < SimpleRecord::Base
4
+
5
+ has_strings :base_string
6
+
7
+ end
@@ -1,34 +1,34 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
2
- require 'my_model'
3
-
4
- class MyChildModel < SimpleRecord::Base
5
- belongs_to :my_model
6
- has_attributes :name, :child_attr
7
-
8
- end
9
-
10
-
11
- =begin
12
-
13
-
14
- puts 'word'
15
-
16
- mm = MyModel.new
17
- puts 'word2'
18
-
19
- mcm = MyChildModel.new
20
-
21
- puts 'mcm instance methods=' + MyChildModel.instance_methods(true).inspect
22
- #puts 'mcm=' + mcm.instance_methods(false)
23
- puts 'mcm class vars = ' + mcm.class.class_variables.inspect
24
- puts mcm.class == MyChildModel
25
- puts 'saved? ' + mm.save.to_s
26
- puts mm.errors.inspect
27
-
28
- puts "mm attributes=" + MyModel.defined_attributes.inspect
29
- puts "mcm attributes=" + MyChildModel.defined_attributes.inspect
30
-
31
- mcm2 = MyChildModel.new
32
- puts "mcm2 attributes=" + MyChildModel.defined_attributes.inspect
33
-
34
- =end
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
2
+ require 'my_model'
3
+
4
+ class MyChildModel < SimpleRecord::Base
5
+ belongs_to :my_model
6
+ has_attributes :name, :child_attr
7
+
8
+ end
9
+
10
+
11
+ =begin
12
+
13
+
14
+ puts 'word'
15
+
16
+ mm = MyModel.new
17
+ puts 'word2'
18
+
19
+ mcm = MyChildModel.new
20
+
21
+ puts 'mcm instance methods=' + MyChildModel.instance_methods(true).inspect
22
+ #puts 'mcm=' + mcm.instance_methods(false)
23
+ puts 'mcm class vars = ' + mcm.class.class_variables.inspect
24
+ puts mcm.class == MyChildModel
25
+ puts 'saved? ' + mm.save.to_s
26
+ puts mm.errors.inspect
27
+
28
+ puts "mm attributes=" + MyModel.defined_attributes.inspect
29
+ puts "mcm attributes=" + MyChildModel.defined_attributes.inspect
30
+
31
+ mcm2 = MyChildModel.new
32
+ puts "mcm2 attributes=" + MyChildModel.defined_attributes.inspect
33
+
34
+ =end
data/test/my_model.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
2
+ require 'my_base_model'
2
3
 
3
- class MyModel < SimpleRecord::Base
4
+ class MyModel < MyBaseModel
4
5
 
5
6
  has_strings :name, :nickname
6
7
  has_ints :age, :save_count
@@ -11,7 +12,7 @@ class MyModel < SimpleRecord::Base
11
12
  #callbacks
12
13
  before_create :set_nickname
13
14
 
14
- after_save :bump_save_count
15
+ before_save :bump_save_count
15
16
 
16
17
  def set_nickname
17
18
  self.nickname = name if self.nickname.blank?
@@ -1,15 +1,15 @@
1
-
2
- require File.expand_path(File.dirname(__FILE__) + "/../lib/results_array")
3
-
4
- array = SimpleRecord::ResultsArray.new()
5
- #array.extend(ResultsArray)
6
-
7
- 500.times do |i|
8
- array << "_ob_" + i.to_s
9
- end
10
-
11
- array.each do |v|
12
- puts v.to_s
13
- end
14
-
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/results_array")
3
+
4
+ array = SimpleRecord::ResultsArray.new()
5
+ #array.extend(ResultsArray)
6
+
7
+ 500.times do |i|
8
+ array << "_ob_" + i.to_s
9
+ end
10
+
11
+ array.each do |v|
12
+ puts v.to_s
13
+ end
14
+
15
15
  puts array[10]
data/test/temp_test.rb CHANGED
@@ -1,63 +1,63 @@
1
- # rubymine won't run 1.9 tests
2
-
3
- require 'minitest/unit'
4
- require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
5
- require "yaml"
6
- require 'right_aws'
7
- require 'my_model'
8
- require 'my_child_model'
9
-
10
-
11
- def setup
12
- @config = YAML::load(File.read('test-config.yml'))
13
- puts 'akey=' + @config['amazon']['access_key']
14
- puts 'skey=' + @config['amazon']['secret_key']
15
- RightAws::ActiveSdb.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :port=>80, :protocol=>"http")
16
- SimpleRecord::Base.set_domain_prefix("simplerecord_tests_")
17
- end
18
-
19
- def teardown
20
- RightAws::ActiveSdb.close_connection()
21
- end
22
-
23
- def test_dates
24
- mm = MyModel.new
25
- mm.name = "Travis"
26
- mm.age = 32
27
- mm.cool = true
28
- mm.created = DateTime.now - 10
29
- mm.updated = DateTime.now
30
- mm.birthday = Time.now - (3600 * 24 * 365 * 10)
31
- puts 'before save=' + mm.inspect
32
- mm.save
33
- puts 'after save=' + mm.inspect
34
-
35
- mms = MyModel.find(:all, :conditions => ["created > ?", DateTime.now - 1])
36
- puts 'mms=' + mms.inspect
37
-
38
- end
39
-
40
- def test_date_comparisons
41
-
42
- t = SimpleRecord::Base.pad_and_offset(Time.now)
43
- puts t
44
- dt = SimpleRecord::Base.pad_and_offset(DateTime.now)
45
- puts dt
46
- dt_tomorrow = SimpleRecord::Base.pad_and_offset(DateTime.now + 1)
47
-
48
-
49
- puts 'compare=' + (t <=> dt).to_s
50
- puts 'compare=' + (t <=> dt_tomorrow).to_s
51
-
52
- dts = DateTime.parse(dt_tomorrow)
53
- puts dts.to_s
54
- ts = Time.parse(dt)
55
- puts ts.to_s
56
- end
57
-
58
- setup
59
-
60
- #test_dates
61
- test_date_comparisons
62
-
63
- teardown
1
+ # rubymine won't run 1.9 tests
2
+
3
+ require 'minitest/unit'
4
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
5
+ require "yaml"
6
+ require 'right_aws'
7
+ require 'my_model'
8
+ require 'my_child_model'
9
+
10
+
11
+ def setup
12
+ @config = YAML::load(File.read('test-config.yml'))
13
+ puts 'akey=' + @config['amazon']['access_key']
14
+ puts 'skey=' + @config['amazon']['secret_key']
15
+ RightAws::ActiveSdb.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :port=>80, :protocol=>"http")
16
+ SimpleRecord::Base.set_domain_prefix("simplerecord_tests_")
17
+ end
18
+
19
+ def teardown
20
+ RightAws::ActiveSdb.close_connection()
21
+ end
22
+
23
+ def test_dates
24
+ mm = MyModel.new
25
+ mm.name = "Travis"
26
+ mm.age = 32
27
+ mm.cool = true
28
+ mm.created = DateTime.now - 10
29
+ mm.updated = DateTime.now
30
+ mm.birthday = Time.now - (3600 * 24 * 365 * 10)
31
+ puts 'before save=' + mm.inspect
32
+ mm.save
33
+ puts 'after save=' + mm.inspect
34
+
35
+ mms = MyModel.find(:all, :conditions => ["created > ?", DateTime.now - 1])
36
+ puts 'mms=' + mms.inspect
37
+
38
+ end
39
+
40
+ def test_date_comparisons
41
+
42
+ t = SimpleRecord::Base.pad_and_offset(Time.now)
43
+ puts t
44
+ dt = SimpleRecord::Base.pad_and_offset(DateTime.now)
45
+ puts dt
46
+ dt_tomorrow = SimpleRecord::Base.pad_and_offset(DateTime.now + 1)
47
+
48
+
49
+ puts 'compare=' + (t <=> dt).to_s
50
+ puts 'compare=' + (t <=> dt_tomorrow).to_s
51
+
52
+ dts = DateTime.parse(dt_tomorrow)
53
+ puts dts.to_s
54
+ ts = Time.parse(dt)
55
+ puts ts.to_s
56
+ end
57
+
58
+ setup
59
+
60
+ #test_dates
61
+ test_date_comparisons
62
+
63
+ teardown
@@ -8,14 +8,19 @@ require 'my_child_model'
8
8
  class TestSimpleRecord < Test::Unit::TestCase
9
9
 
10
10
  def setup
11
- @config = YAML::load(File.open(File.expand_path("~/.amazon/simple_record_tests.yml")))
12
- #puts @config.inspect
13
- SimpleRecord.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :port=>80, :protocol=>"http")
11
+ @config = YAML::load(File.open(File.expand_path("~/.test-configs/simple_record.yml")))
12
+ #puts 'inspecting config = ' + @config.inspect
13
+
14
+ # Establish AWS connection directly
15
+ @@sdb = RightAws::SdbInterface.new(@config['amazon']['access_key'], @config['amazon']['secret_key'], {:connection_mode => :per_request, :protocol => "http", :port => 80})
16
+
17
+
18
+ SimpleRecord.establish_connection(@config['amazon']['access_key'], @config['amazon']['secret_key'], :connection_mode=>:single)
14
19
  SimpleRecord::Base.set_domain_prefix("simplerecord_tests_")
15
20
  end
16
21
 
17
22
  def teardown
18
- SimpleRecord.close_connection()
23
+ SimpleRecord.close_connection
19
24
  end
20
25
 
21
26
 
@@ -46,6 +51,15 @@ class TestSimpleRecord < Test::Unit::TestCase
46
51
  assert mm2.cool = true
47
52
  assert mm2.name = "Travis"
48
53
  assert mm2.created.is_a? DateTime
54
+
55
+ # test nilification
56
+ mm2.age = nil
57
+ mm2.save
58
+ puts mm2.errors.inspect
59
+ sleep 1
60
+ mm2 = MyModel.find(id)
61
+ puts mm2.inspect
62
+ assert mm2.age.nil?, "doh, age is " + mm2.age.inspect
49
63
  end
50
64
 
51
65
  def test_bad_query
@@ -133,7 +147,7 @@ class TestSimpleRecord < Test::Unit::TestCase
133
147
  mm2.name = "Travis 2"
134
148
  mm2.save(:dirty=>true)
135
149
 
136
- # todo: how do we assert this?
150
+ # todo: how do we assert this? perhaps change a value directly in sdb and see that it doesn't get overwritten
137
151
 
138
152
  end
139
153
 
@@ -206,14 +220,7 @@ class TestSimpleRecord < Test::Unit::TestCase
206
220
 
207
221
  # ensures that it uses next token and what not
208
222
  def test_big_result
209
- mms = MyModel.find(:all)
210
- puts 'mms.size=' + mms.size.to_s
211
- i = 0
212
- mms.each do |x|
213
- puts 'deleting=' + i.to_s
214
- x.delete
215
- i+=1
216
- end
223
+ i = clear_out_my_models
217
224
  num_made = 110
218
225
  num_made.times do |i|
219
226
  mm = MyModel.create(:name=>"Travis", :age=>i, :cool=>true)
@@ -228,6 +235,17 @@ class TestSimpleRecord < Test::Unit::TestCase
228
235
  assert i == num_made
229
236
  end
230
237
 
238
+ def clear_out_my_models
239
+ mms = MyModel.find(:all)
240
+ puts 'mms.size=' + mms.size.to_s
241
+ i = 0
242
+ mms.each do |x|
243
+ puts 'deleting=' + i.to_s
244
+ x.delete
245
+ i+=1
246
+ end
247
+ end
248
+
231
249
  def test_results_array
232
250
  mms = MyModel.find(:all) # select 2
233
251
  assert !mms.first.nil?
@@ -294,7 +312,80 @@ class TestSimpleRecord < Test::Unit::TestCase
294
312
 
295
313
  assert mm.valid?, mm.errors.inspect
296
314
  assert mm.save_count == 1
315
+ end
316
+
317
+
318
+ def test_nil_attr_deletion
319
+ mm = MyModel.new
320
+ mm.name = "Chad"
321
+ mm.age = 30
322
+ mm.cool = false
323
+ mm.save
324
+
325
+ # Should have 1 age attribute
326
+ assert @@sdb.get_attributes('simplerecord_tests_mymodel', mm.id, 'age')[:attributes].size == 1
327
+
328
+ mm.age = nil
329
+ mm.save
330
+
331
+ # Should be NIL
332
+ assert mm.age == nil
333
+
334
+ # Should have NO age attributes
335
+ assert @@sdb.get_attributes('simplerecord_tests_mymodel', mm.id, 'age')[:attributes].size == 0
336
+ end
337
+
338
+ def test_null
339
+ puts Time.now.to_i.to_s
340
+ clear_out_my_models
341
+
342
+ mm = MyModel.new(:name=>"birthay is null")
343
+ mm.save
344
+ mm2 = MyModel.new(:name=>"birthday is not null")
345
+ mm2.birthday = Time.now
346
+ mm2.save
347
+ sleep 2
348
+ mms = MyModel.find(:all, :conditions=>["birthday is null"])
349
+ mms.each do |m|
350
+ puts m.inspect
351
+ end
352
+ assert mms.size == 1
353
+ assert mms[0].id = mm.id
354
+ mms = MyModel.find(:all, :conditions=>["birthday is not null"])
355
+ mms.each do |m|
356
+ puts m.inspect
357
+ end
358
+ assert mms.size == 1
359
+ assert mms[0].id = mm2.id
360
+
361
+ end
362
+
363
+ # Test to add support for IN
364
+ def test_in_clause
365
+ mms = MyModel.find(:all)
366
+
367
+ mms2 = MyModel.find(:all, :conditions=>["id in ?"])
297
368
 
298
369
  end
299
370
 
371
+ def test_base_attributes
372
+ mm = MyModel.new()
373
+ mm.name = "test name"
374
+ mm.base_string = "in base class"
375
+ mm.save_with_validation!
376
+
377
+ mm2 = MyModel.find(mm.id)
378
+ assert mm2.base_string == mm.base_string
379
+
380
+ mm2.base_string = "changed base string"
381
+ mm2.save_with_validation!
382
+
383
+ mm3 = MyModel.find(mm2.id)
384
+ assert mm3.base_string == mm2.base_string
385
+ puts mm3.inspect
386
+
387
+
388
+ end
389
+
390
+
300
391
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.24
4
+ version: 1.1.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Reeder
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2009-10-12 00:00:00 -07:00
14
+ date: 2009-10-29 00:00:00 -07:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -66,6 +66,8 @@ signing_key:
66
66
  specification_version: 3
67
67
  summary: Drop in replacement for ActiveRecord to Amazon SimpleDB instead.
68
68
  test_files:
69
+ - test/conversions.rb
70
+ - test/my_base_model.rb
69
71
  - test/my_child_model.rb
70
72
  - test/my_model.rb
71
73
  - test/paging_array_test.rb