simple_record 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -70,6 +70,11 @@ This is required because SimpleDB only has strings so SimpleRecord needs to know
70
70
  has_booleans :is_nerd
71
71
  end
72
72
 
73
+ ### Multi-value attributes
74
+
75
+ SimpleDB supports having multiple values for the same attribute so to use this feature, simply set an attribute to an
76
+ array of values.
77
+
73
78
  ### belongs_to
74
79
 
75
80
  Creates a many-to-one relationship. Can only have one per belongs_to call.
@@ -207,13 +212,34 @@ Use per_thread connection mode and close the connection after each request.
207
212
 
208
213
  ### Disable ActiveRecord so you don't have to setup another database
209
214
 
210
- This is most helpful on windows so Rails doesn't need sqlite or mysql gems/drivers installed which are painful to install on windows. In environment.rb, add 'config.frameworks -= [ :active_record ]', should look something like:
215
+ #### Rails 2
216
+
217
+ This is most helpful on windows so Rails doesn't need sqlite or mysql gems/drivers installed which are painful to install on windows.
218
+ In environment.rb, add 'config.frameworks -= [ :active_record ]', so it should look something like:
211
219
 
212
220
  Rails::Initializer.run do |config|
213
221
  config.frameworks -= [ :active_record ]
214
222
  ....
215
223
  end
216
224
 
225
+ #### Rails 3
226
+
227
+ At the top of application.rb, comment out `require 'rails/all` and add the following:
228
+
229
+ #require 'rails/all'
230
+ %w(
231
+ action_controller
232
+ action_mailer
233
+ active_resource
234
+ rails/test_unit
235
+ ).each do |framework|
236
+ begin
237
+ require "#{framework}/railtie"
238
+ rescue LoadError
239
+ end
240
+ end
241
+
242
+ This is the same as rails/all minus active_record.
217
243
 
218
244
  ## Large Objects (LOBS)
219
245
 
data/lib/simple_record.rb CHANGED
@@ -28,6 +28,13 @@ require 'aws'
28
28
  require 'base64'
29
29
  require 'active_support'
30
30
  require 'active_support/core_ext'
31
+ begin
32
+ # comment out line below to test rails2 validations
33
+ require 'active_model'
34
+ rescue LoadError => ex
35
+ puts "ActiveModel not available, falling back."
36
+ end
37
+ require File.expand_path(File.dirname(__FILE__) + "/simple_record/validations")
31
38
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/attributes")
32
39
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/active_sdb")
33
40
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/callbacks")
@@ -36,7 +43,6 @@ require File.expand_path(File.dirname(__FILE__) + "/simple_record/errors")
36
43
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/json")
37
44
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/logging")
38
45
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/password")
39
- require File.expand_path(File.dirname(__FILE__) + "/simple_record/rails2")
40
46
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/results_array")
41
47
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/stats")
42
48
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/translations")
@@ -170,14 +176,28 @@ module SimpleRecord
170
176
 
171
177
 
172
178
  # puts 'Is ActiveModel defined? ' + defined?(ActiveModel).inspect
179
+
180
+
173
181
  if defined?(ActiveModel)
182
+ @@active_model = true
174
183
  extend ActiveModel::Naming
175
184
  include ActiveModel::Conversion
176
185
  include ActiveModel::Validations
186
+ extend ActiveModel::Callbacks # for ActiveRecord like callbacks
187
+ include ActiveModel::Validations::Callbacks
188
+ define_model_callbacks :save, :create, :update, :destroy
189
+ include SimpleRecord::Callbacks3
190
+ alias_method :am_valid?, :valid?
191
+
192
+
177
193
  else
194
+ @@active_model = false
195
+ puts "using rails2 validations."
178
196
  attr_accessor :errors
179
- include SimpleRecord::Rails2
197
+ include SimpleRecord::Callbacks
180
198
  end
199
+ include SimpleRecord::Validations
200
+
181
201
 
182
202
  include SimpleRecord::Translations
183
203
  # include SimpleRecord::Attributes
@@ -185,7 +205,6 @@ module SimpleRecord
185
205
  include SimpleRecord::Attributes
186
206
  extend SimpleRecord::Sharding::ClassMethods
187
207
  include SimpleRecord::Sharding
188
- include SimpleRecord::Callbacks
189
208
  include SimpleRecord::Json
190
209
  include SimpleRecord::Logging
191
210
  extend SimpleRecord::Logging::ClassMethods
@@ -362,11 +381,10 @@ module SimpleRecord
362
381
  end
363
382
 
364
383
  def clear_errors
365
- # @errors=SimpleRecord_errors.new
366
- if not (defined?(ActiveModel))
367
- @errors=SimpleRecord_errors.new
368
- else
384
+ if defined?(ActiveModel)
369
385
  @errors = ActiveModel::Errors.new(self)
386
+ else
387
+ @errors=SimpleRecord_errors.new
370
388
  end
371
389
  end
372
390
 
@@ -398,9 +416,6 @@ module SimpleRecord
398
416
  self.updated
399
417
  end
400
418
 
401
- def read_attribute_for_validation(key)
402
- @attributes[key.to_s]
403
- end
404
419
 
405
420
  def cache_store
406
421
  @@cache_store
@@ -429,8 +444,9 @@ module SimpleRecord
429
444
  # - :dirty => true - Will only store attributes that were modified. To make it save regardless and have it update the :updated value, include this and set it to false.
430
445
  # - :domain => Explicitly define domain to use.
431
446
  #
447
+
432
448
  def save(options={})
433
- # puts 'SAVING: ' + self.inspect if SimpleRecord.logging?
449
+ puts 'SAVING: ' + self.inspect if SimpleRecord.logging?
434
450
  # todo: Clean out undefined values in @attributes (in case someone set the attributes hash with values that they hadn't defined)
435
451
  clear_errors
436
452
  # todo: decide whether this should go before pre_save or after pre_save? pre_save dirties "updated" and perhaps other items due to callbacks
@@ -441,6 +457,7 @@ module SimpleRecord
441
457
  is_create = self[:id].nil?
442
458
  ok = pre_save(options) # Validates and sets ID
443
459
  if ok
460
+ # puts 'ok'
444
461
  begin
445
462
  dirty = @dirty
446
463
  # puts 'dirty before=' + @dirty.inspect
@@ -449,48 +466,119 @@ module SimpleRecord
449
466
  return true if @dirty.size == 0 # This should probably never happen because after pre_save, created/updated dates are changed
450
467
  options[:dirty_atts] = @dirty
451
468
  end
452
- to_delete = get_atts_to_delete
453
- SimpleRecord.stats.saves += 1
469
+ to_delete = get_atts_to_delete
470
+
454
471
 
455
472
  if self.class.is_sharded?
456
473
  options[:domain] = sharded_domain
457
474
  end
458
475
 
459
- if super(options)
460
- self.class.cache_results(self)
461
- delete_niled(to_delete)
462
- save_lobs(dirty)
463
- after_save_cleanup
464
- if (is_create ? run_after_create : run_after_update) && run_after_save
465
- # puts 'all good?'
466
- return true
467
- else
468
- return false
469
- end
476
+ if @@active_model
477
+ x = save_super(dirty, is_create, options, to_delete)
478
+ # puts 'save_super result = ' + x.to_s
479
+ return x
470
480
  else
471
- return false
481
+ # puts 'not activemodel callbacks'
482
+ return save_super(dirty, is_create, options, to_delete)
472
483
  end
473
484
  rescue Aws::AwsError => ex
474
- # puts "RESCUED in save: " + $!
475
- # Domain is created in aws lib now using :create_domain=>true
476
- # if (domain_ok(ex, options))
477
- # if !@create_domain_called
478
- # @create_domain_called = true
479
- # save(options)
480
- # else
481
- # raise $!
482
- # end
483
- # else
484
- # raise $!
485
- # end
486
485
  raise ex
487
486
  end
488
487
  else
489
- #@debug = "not saved"
488
+ # puts 'returning false'
490
489
  return false
491
490
  end
492
491
  end
493
492
 
493
+ if @@active_model
494
+ alias_method :old_save, :save
495
+
496
+ def save(options={})
497
+ # puts 'extended save'
498
+ x = create_or_update
499
+ # puts 'save x=' + x.to_s
500
+ x
501
+ end
502
+ end
503
+
504
+ def create_or_update #:nodoc:
505
+ # puts 'create_or_update'
506
+ ret = true
507
+ _run_save_callbacks do
508
+ result = new_record? ? create : update
509
+ # puts 'save_callbacks result=' + result.inspect
510
+ ret = result
511
+ end
512
+ ret
513
+ end
514
+
515
+ def create #:nodoc:
516
+ puts '3 create'
517
+ ret = true
518
+ _run_create_callbacks do
519
+ x = old_save
520
+ # puts 'create old_save result=' + x.to_s
521
+ ret = x
522
+ end
523
+ ret
524
+ end
525
+
526
+ #
527
+ def update(*) #:nodoc:
528
+ puts '3 update'
529
+ ret = true
530
+ _run_update_callbacks do
531
+ x = old_save
532
+ # puts 'update old_save result=' + x.to_s
533
+ ret = x
534
+ end
535
+ ret
536
+ end
537
+
538
+
539
+ def save!(options={})
540
+ save(options) || raise(RecordNotSaved.new(self))
541
+ end
542
+
543
+ # this is a bit wonky, save! should call this, not sure why it's here.
544
+ def save_with_validation!(options={})
545
+ save!
546
+ end
547
+
548
+ def self.create(attributes={})
549
+ # puts "About to create in domain #{domain}"
550
+ super
551
+ end
552
+
553
+ def self.create!(attributes={})
554
+ item = self.new(attributes)
555
+ item.save!
556
+ item
557
+ end
558
+
559
+
560
+ def save_super(dirty, is_create, options, to_delete)
561
+ SimpleRecord.stats.saves += 1
562
+ if save2(options)
563
+ self.class.cache_results(self)
564
+ delete_niled(to_delete)
565
+ save_lobs(dirty)
566
+ after_save_cleanup
567
+ unless @@active_model
568
+ if (is_create ? run_after_create : run_after_update) && run_after_save
569
+ # puts 'all good?'
570
+ return true
571
+ else
572
+ return false
573
+ end
574
+ end
575
+ return true
576
+ else
577
+ return false
578
+ end
579
+ end
580
+
581
+
494
582
  def save_lobs(dirty=nil)
495
583
  # puts 'dirty.inspect=' + dirty.inspect
496
584
  dirty = @dirty if dirty.nil?
@@ -600,26 +688,6 @@ module SimpleRecord
600
688
  "lobs/#{self.id}_single_clob"
601
689
  end
602
690
 
603
- def save!(options={})
604
- save(options) || raise(RecordNotSaved.new(nil, self))
605
- end
606
-
607
- # this is a bit wonky, save! should call this, not sure why it's here.
608
- def save_with_validation!(options={})
609
- save!
610
- end
611
-
612
- def self.create(attributes={})
613
- # puts "About to create in domain #{domain}"
614
- super
615
- end
616
-
617
- def self.create!(attributes={})
618
- item = self.new(attributes)
619
- item.save!
620
- item
621
- end
622
-
623
691
 
624
692
  def self.get_encryption_key()
625
693
  key = SimpleRecord.options[:encryption_key]
@@ -630,28 +698,20 @@ module SimpleRecord
630
698
  return key
631
699
  end
632
700
 
633
- def validate
634
- true
635
- end
636
-
637
- def validate_on_create
638
- true
639
- end
640
-
641
- def validate_on_update
642
- true
643
- end
644
-
645
-
646
701
  def pre_save(options)
647
702
 
703
+
704
+ ok = true
648
705
  is_create = self[:id].nil?
649
- ok = run_before_validation && (is_create ? run_before_validation_on_create : run_before_validation_on_update)
650
- return false unless ok
706
+ unless @@active_model
707
+ ok = run_before_validation && (is_create ? run_before_validation_on_create : run_before_validation_on_update)
708
+ return false unless ok
709
+ end
651
710
 
652
711
  # validate()
653
712
  # is_create ? validate_on_create : validate_on_update
654
713
  if !valid?
714
+ puts 'not valid'
655
715
  return false
656
716
  end
657
717
  #
@@ -661,23 +721,26 @@ module SimpleRecord
661
721
  # return false
662
722
  # end
663
723
 
664
- ok = run_after_validation && (is_create ? run_after_validation_on_create : run_after_validation_on_update)
665
- return false unless ok
724
+ unless @@active_model
725
+ ok = run_after_validation && (is_create ? run_after_validation_on_create : run_after_validation_on_update)
726
+ return false unless ok
727
+ end
666
728
 
667
- ok = respond_to?('before_save') ? before_save : true
668
- if ok
669
- if is_create && respond_to?('before_create')
670
- ok = before_create
671
- elsif !is_create && respond_to?('before_update')
672
- ok = before_update
729
+ # Now for callbacks
730
+ unless @@active_model
731
+ ok = respond_to?('before_save') ? before_save : true
732
+ if ok
733
+ if is_create && respond_to?('before_create')
734
+ ok = before_create
735
+ elsif !is_create && respond_to?('before_update')
736
+ ok = before_update
737
+ end
673
738
  end
674
- end
675
- if ok
676
- ok = run_before_save && (is_create ? run_before_create : run_before_update)
677
- end
678
- if ok
679
- # Now translate all fields into SimpleDB friendly strings
680
- # convert_all_atts_to_sdb()
739
+ if ok
740
+ ok = run_before_save && (is_create ? run_before_create : run_before_update)
741
+ end
742
+ else
743
+
681
744
  end
682
745
  prepare_for_update
683
746
  ok
@@ -779,10 +842,15 @@ module SimpleRecord
779
842
  end
780
843
 
781
844
  def destroy
782
- return run_before_destroy && delete && run_after_destroy
845
+ if @@active_model
846
+ _run_destroy_callbacks do
847
+ delete
848
+ end
849
+ else
850
+ return run_before_destroy && delete && run_after_destroy
851
+ end
783
852
  end
784
853
 
785
-
786
854
  def delete_niled(to_delete)
787
855
  # puts 'to_delete=' + to_delete.inspect
788
856
  if to_delete.size > 0
@@ -861,6 +929,11 @@ module SimpleRecord
861
929
  if params.size > 1
862
930
  options = params[1]
863
931
  end
932
+ conditions = options[:conditions]
933
+ if conditions && conditions.is_a?(String)
934
+ conditions = [conditions]
935
+ options[:conditions] = conditions
936
+ end
864
937
 
865
938
  if !options[:shard_find] && is_sharded?
866
939
  # then break off and get results across all shards
@@ -958,7 +1031,8 @@ module SimpleRecord
958
1031
  def self.convert_condition_params(options)
959
1032
  return if options.nil?
960
1033
  conditions = options[:conditions]
961
- if !conditions.nil? && conditions.size > 1
1034
+ return if conditions.nil?
1035
+ if conditions.size > 1
962
1036
  # all after first are values
963
1037
  conditions.collect! { |x|
964
1038
  Translations.pad_and_offset(x)
@@ -856,7 +856,7 @@ module SimpleRecord
856
856
  # - :except => Array of attributes to NOT save
857
857
  #
858
858
  # compare to +put+ method
859
- def save(options={})
859
+ def save2(options={})
860
860
  options[:create_domain] = true if options[:create_domain].nil?
861
861
  pre_save2
862
862
  atts_to_save = @attributes.dup
@@ -346,14 +346,14 @@ module SimpleRecord
346
346
  begin
347
347
  single_clob = s3_bucket(false, :s3_bucket=>:new).get(single_clob_id)
348
348
  single_clob = JSON.parse(single_clob)
349
- puts "single_clob=" + single_clob.inspect
349
+ # puts "single_clob=" + single_clob.inspect
350
350
  single_clob.each_pair do |name2,val|
351
351
  @lobs[name2.to_sym] = val
352
352
  end
353
353
  ret = @lobs[name]
354
354
  SimpleRecord.stats.s3_gets += 1
355
355
  rescue Aws::AwsError => ex
356
- if ex.include? /NoSuchKey/
356
+ if ex.include?(/NoSuchKey/) || ex.include?(/NoSuchBucket/)
357
357
  ret = nil
358
358
  else
359
359
  raise ex
@@ -365,7 +365,7 @@ module SimpleRecord
365
365
  # puts 'got from s3 ' + ret.inspect
366
366
  SimpleRecord.stats.s3_gets += 1
367
367
  rescue Aws::AwsError => ex
368
- if ex.include? /NoSuchKey/
368
+ if ex.include?(/NoSuchKey/) || ex.include?(/NoSuchBucket/)
369
369
  ret = nil
370
370
  else
371
371
  raise ex