simple_record 1.1.72 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -2,17 +2,11 @@
2
2
 
3
3
  An ActiveRecord interface for SimpleDB. Can be used as a drop in replacement for ActiveRecord in rails.
4
4
 
5
- ## Full Documentation
6
-
7
- [http://sites.appoxy.com/simple_record/]
5
+ Brought to you by: [![Appoxy](http://www.simpledeployr.com/images/global/appoxy-small.png)](http://www.appoxy.com)
8
6
 
9
7
  ## Discussion Group
10
8
 
11
- [http://groups.google.com/group/simple-record]
12
-
13
- ## Issue Tracking
14
-
15
- [http://appoxy.lighthouseapp.com/projects/38366-simplerecord/overview]
9
+ <http://groups.google.com/group/simple-record>
16
10
 
17
11
  ## Getting Started
18
12
 
@@ -130,6 +124,14 @@ but this should get you started.
130
124
  You can get more ideas from here: http://api.rubyonrails.org/classes/ActiveRecord/Base.html. Not everything is supported
131
125
  but a lot is.
132
126
 
127
+ ### Pagination
128
+
129
+ SimpleRecord has paging built in and acts much like will_paginate:
130
+
131
+ MyModel.paginate(:page=>2, :per_page=>30 [, the other normal query options like in find()])
132
+
133
+ That will return results 30 to 59.
134
+
133
135
  ## Configuration
134
136
 
135
137
  ### Domain Prefix
@@ -235,6 +237,30 @@ You can use any cache that supports the ActiveSupport::Cache::Store interface.
235
237
  If you want a simple in memory cache store, try: http://gemcutter.org/gems/local_cache . It supports max cache size and
236
238
  timeouts. You can also use memcached or http://www.quetzall.com/cloudcache.
237
239
 
240
+ ## Encryption
241
+
242
+ SimpleRecord has built in support for encrypting attributes with AES-256 encryption and one way hashing using SHA-512 (good for passwords). And it's easy to use.
243
+
244
+ Here is an example of a model with an encrypted attribute and a hashed attribute.
245
+
246
+ class ModelWithEnc < SimpleRecord::Base
247
+ has_strings :name,
248
+ {:name=>:ssn, :encrypted=>"simple_record_test_key"},
249
+ {:name=>:password, :hashed=>true}
250
+ end
251
+
252
+ The :encrypted option takes a key that you specify. The attribute can only be decrypted with the exact same key.
253
+
254
+ The :hashed option is simply true/false.
255
+
256
+ Encryption is generally transparent to you, SimpleRecord will store the encrypted value in the database and unencrypt it when you use it.
257
+
258
+ Hashing is not quite as transparent as it cannot be converted back to it's original value, but you can do easy comparisons with it, for instance:
259
+
260
+ ob2.password == "mypassword"
261
+
262
+ This will actually be compared by hashing "mypassword" first.
263
+
238
264
  ## Kudos
239
265
 
240
266
  Special thanks to Garrett Cox for creating Activerecord2sdb which SimpleRecord is based on:
@@ -0,0 +1,6 @@
1
+ module SimpleRecord
2
+
3
+ class RecordNotSaved < StandardError
4
+
5
+ end
6
+ end
@@ -18,9 +18,9 @@ module SimpleRecord
18
18
  att_meta = defined_attributes_local[name.to_sym]
19
19
 
20
20
  if att_meta.type == :int
21
- ret = Translations.pad_and_offset(value)
21
+ ret = Translations.pad_and_offset(value, att_meta)
22
22
  elsif att_meta.type == :date
23
- ret = Translations.pad_and_offset(value)
23
+ ret = Translations.pad_and_offset(value, att_meta)
24
24
  else
25
25
  ret = value.to_s
26
26
  end
@@ -104,7 +104,7 @@ module SimpleRecord
104
104
  end
105
105
 
106
106
 
107
- def self.pad_and_offset(x) # Change name to something more appropriate like ruby_to_sdb
107
+ def self.pad_and_offset(x, att_meta=nil) # Change name to something more appropriate like ruby_to_sdb
108
108
  # todo: add Float, etc
109
109
  # puts 'padding=' + x.class.name + " -- " + x.inspect
110
110
  if x.kind_of? Integer
data/lib/simple_record.rb CHANGED
@@ -27,9 +27,10 @@
27
27
  require 'aws'
28
28
  require 'sdb/active_sdb'
29
29
  require 'base64'
30
- require File.expand_path(File.dirname(__FILE__) + "/simple_record/encryptor")
31
- require File.expand_path(File.dirname(__FILE__) + "/simple_record/callbacks")
32
30
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/attributes")
31
+ require File.expand_path(File.dirname(__FILE__) + "/simple_record/callbacks")
32
+ require File.expand_path(File.dirname(__FILE__) + "/simple_record/encryptor")
33
+ require File.expand_path(File.dirname(__FILE__) + "/simple_record/exceptions")
33
34
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/errors")
34
35
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/password")
35
36
  require File.expand_path(File.dirname(__FILE__) + "/simple_record/results_array")
@@ -41,6 +42,15 @@ module SimpleRecord
41
42
 
42
43
  @@options = {}
43
44
  @@stats = SimpleRecord::Stats.new
45
+ @@logging = false
46
+
47
+ def self.enable_logging
48
+ @@logging = true
49
+ end
50
+
51
+ def self.disable_logging
52
+ @@logging = false
53
+ end
44
54
 
45
55
  def self.stats
46
56
  @@stats
@@ -83,6 +93,13 @@ module SimpleRecord
83
93
  extend SimpleRecord::Attributes
84
94
  include SimpleRecord::Callbacks
85
95
 
96
+ # Too many ActiveRecord dependencies.
97
+ # if Gem.available?('will_paginate')
98
+ # require 'will_paginate/finder'
99
+ # include WillPaginate::Finder
100
+ # end
101
+
102
+
86
103
 
87
104
  def initialize(attrs={})
88
105
  # 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
@@ -374,6 +391,10 @@ module SimpleRecord
374
391
  end
375
392
  end
376
393
 
394
+ def save!(options={})
395
+ save(options) || raise(RecordNotSaved)
396
+ end
397
+
377
398
  def save_with_validation!(options={})
378
399
  if valid?
379
400
  save
@@ -429,24 +450,6 @@ module SimpleRecord
429
450
  ok
430
451
  end
431
452
 
432
- def save_attributes(atts)
433
- # puts 'atts=' + atts.inspect
434
- ret = super(atts)
435
- # puts '@atts=' + @attributes.inspect
436
- atts.each_pair do |k, v|
437
- @attributes[k.to_s] = v
438
- if k.is_a?(Symbol)
439
- @attributes.delete(k)
440
- end
441
- end
442
- # puts '@atts2=' + @attributes.inspect
443
- @attributes_rb = {} unless @attributes_rb # was getting errors after upgrade.
444
- @attributes_rb.clear # clear out the ruby versions so they can reload on next get.
445
- if ret
446
- self.class.cache_results(self)
447
- end
448
- ret
449
- end
450
453
 
451
454
  def get_atts_to_delete
452
455
  # todo: this should use the @dirty hash now
@@ -570,8 +573,8 @@ module SimpleRecord
570
573
  attvalue = value.nil? ? nil : value.id
571
574
  else
572
575
  attname = name.to_s
573
- # attvalue = att_meta.init_value(value)
574
- attvalue = value
576
+ attvalue = att_meta.init_value(value)
577
+ # attvalue = value
575
578
  #puts 'converted ' + value.inspect + ' to ' + attvalue.inspect
576
579
  end
577
580
  end
@@ -603,10 +606,18 @@ module SimpleRecord
603
606
  super()
604
607
  end
605
608
 
609
+
606
610
  def update_attributes(atts)
607
- return save_attributes(atts)
611
+ set_attributes(atts)
612
+ save
613
+ end
614
+
615
+ def update_attributes!(atts)
616
+ set_attributes(atts)
617
+ save!
608
618
  end
609
619
 
620
+
610
621
  def self.quote_regexp(a, re)
611
622
  a =~ re
612
623
  #was there a match?
@@ -690,6 +701,50 @@ module SimpleRecord
690
701
  return find(*params)
691
702
  end
692
703
 
704
+ def self.all(*args)
705
+ find(:all, *args)
706
+ end
707
+
708
+ def self.first(*args)
709
+ find(:first, *args)
710
+ end
711
+
712
+ def self.count(*args)
713
+ find(:count, *args)
714
+ end
715
+
716
+ # This gets less and less efficient the higher the page since SimpleDB has no way
717
+ # to start at a specific row. So it will iterate from the first record and pull out the specific pages.
718
+ def self.paginate(options={})
719
+ # options = args.pop
720
+ puts 'paginate options=' + options.inspect if @@logging
721
+ page = options[:page] || 1
722
+ per_page = options[:per_page] || self.per_page || 50
723
+ total = options[:total_entries]
724
+ options[:limit] = page * per_page
725
+ fr = find(:all, options)
726
+ puts 'fr.size=' + fr.size.to_s
727
+ ret = []
728
+ i = 0
729
+ p = 1
730
+ fr.each do |x|
731
+ # puts 'x=' + x.inspect
732
+ if p == page
733
+ # puts 'adding'
734
+ ret << x
735
+ end
736
+ i += 1
737
+ if i > 0 && i % per_page == 0
738
+ p += 1
739
+ if p > page
740
+ break
741
+ end
742
+ end
743
+ end
744
+ ret
745
+ end
746
+
747
+
693
748
  def self.convert_condition_params(options)
694
749
  return if options.nil?
695
750
  conditions = options[:conditions]
@@ -759,6 +814,13 @@ module SimpleRecord
759
814
  id.hash
760
815
  end
761
816
 
817
+ private
818
+ def set_attributes(atts)
819
+ atts.each_pair do |k, v|
820
+ set(k, v)
821
+ end
822
+ end
823
+
762
824
  end
763
825
 
764
826
 
@@ -1,8 +1,8 @@
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
-
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
+
8
8
  end
@@ -1,35 +1,35 @@
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
- belongs_to :x, :class_name=>"MyModel"
7
- has_attributes :name, :child_attr
8
-
9
- end
10
-
11
-
12
- =begin
13
-
14
-
15
- puts 'word'
16
-
17
- mm = MyModel.new
18
- puts 'word2'
19
-
20
- mcm = MyChildModel.new
21
-
22
- puts 'mcm instance methods=' + MyChildModel.instance_methods(true).inspect
23
- #puts 'mcm=' + mcm.instance_methods(false)
24
- puts 'mcm class vars = ' + mcm.class.class_variables.inspect
25
- puts mcm.class == MyChildModel
26
- puts 'saved? ' + mm.save.to_s
27
- puts mm.errors.inspect
28
-
29
- puts "mm attributes=" + MyModel.defined_attributes.inspect
30
- puts "mcm attributes=" + MyChildModel.defined_attributes.inspect
31
-
32
- mcm2 = MyChildModel.new
33
- puts "mcm2 attributes=" + MyChildModel.defined_attributes.inspect
34
-
35
- =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
+ belongs_to :x, :class_name=>"MyModel"
7
+ has_attributes :name, :child_attr
8
+
9
+ end
10
+
11
+
12
+ =begin
13
+
14
+
15
+ puts 'word'
16
+
17
+ mm = MyModel.new
18
+ puts 'word2'
19
+
20
+ mcm = MyChildModel.new
21
+
22
+ puts 'mcm instance methods=' + MyChildModel.instance_methods(true).inspect
23
+ #puts 'mcm=' + mcm.instance_methods(false)
24
+ puts 'mcm class vars = ' + mcm.class.class_variables.inspect
25
+ puts mcm.class == MyChildModel
26
+ puts 'saved? ' + mm.save.to_s
27
+ puts mm.errors.inspect
28
+
29
+ puts "mm attributes=" + MyModel.defined_attributes.inspect
30
+ puts "mcm attributes=" + MyChildModel.defined_attributes.inspect
31
+
32
+ mcm2 = MyChildModel.new
33
+ puts "mcm2 attributes=" + MyChildModel.defined_attributes.inspect
34
+
35
+ =end
data/test/my_model.rb CHANGED
@@ -19,13 +19,13 @@ class MyModel < MyBaseModel
19
19
  end
20
20
 
21
21
  def bump_save_count
22
- puts 'save_count=' + save_count.to_s
22
+ # puts 'save_count=' + save_count.to_s
23
23
  if save_count.nil?
24
24
  self.save_count = 1
25
25
  else
26
26
  self.save_count += 1
27
27
  end
28
- puts 'save_count=' + self.save_count.to_s
28
+ # puts 'save_count=' + self.save_count.to_s
29
29
  end
30
30
 
31
31
  def validate
@@ -37,7 +37,7 @@ class MyModel < MyBaseModel
37
37
  end
38
38
 
39
39
  def validate_on_update
40
- puts 'save_count = ' + save_count.to_s
40
+ # puts 'save_count = ' + save_count.to_s
41
41
  errors.add("save_count", "should not be zero.") if save_count.blank? || save_count == 0
42
42
  end
43
43
 
@@ -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/test_base.rb CHANGED
@@ -32,4 +32,19 @@ class TestBase < Test::Unit::TestCase
32
32
 
33
33
  end
34
34
 
35
+
36
+ # Use to populate db
37
+ def create_my_models(count)
38
+ batch = []
39
+ count.times do |i|
40
+ mm = MyModel.new(:name=>"model_" + i.to_s)
41
+ batch << mm
42
+ end
43
+ MyModel.batch_save batch
44
+
45
+ sleep 2
46
+
47
+ end
48
+
49
+
35
50
  end
@@ -0,0 +1,43 @@
1
+ require 'test/unit'
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/simple_record")
3
+ require "yaml"
4
+ require 'aws'
5
+ require 'my_model'
6
+ require 'my_child_model'
7
+ require 'active_support'
8
+ require 'test_base'
9
+
10
+
11
+ class Person < SimpleRecord::Base
12
+ has_strings :name, :i_as_s
13
+ has_ints :age, :i2
14
+ end
15
+ class DirtyTest < TestBase
16
+
17
+ def setup
18
+ super
19
+
20
+ Person.create_domain
21
+ @person = Person.new(:name => 'old', :age => 70)
22
+ @person.save
23
+
24
+ assert !@person.changed?
25
+ assert !@person.name_changed?
26
+ end
27
+
28
+ def teardown
29
+ Person.delete_domain
30
+ SimpleRecord.close_connection
31
+ end
32
+
33
+ def test_string_on_initialize
34
+ p = Person.new(:name=>"Travis", :age=>5, :i2=>"6")
35
+ assert p.name == "Travis"
36
+ assert p.age == 5
37
+ assert p.i2 == 6, "i2 == #{p.i2}"
38
+
39
+
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,28 @@
1
+ require 'test/unit'
2
+ require File.join(File.dirname(__FILE__), "/../lib/simple_record")
3
+ require File.join(File.dirname(__FILE__), "./test_helpers")
4
+ require File.join(File.dirname(__FILE__), "./test_base")
5
+ require "yaml"
6
+ require 'aws'
7
+ require 'my_model'
8
+ require 'my_child_model'
9
+ require 'model_with_enc'
10
+ require 'active_support'
11
+
12
+
13
+ # Pagination is intended to be just like will_paginate.
14
+ class TestPagination < TestBase
15
+
16
+ def test_paginate
17
+ create_my_models(20)
18
+
19
+ (1..3).each do |page|
20
+ models = MyModel.paginate :page=>page, :per_page=>5, :order=>"name"
21
+ assert models.size == 5
22
+ models.each do |m|
23
+ puts m.name
24
+ end
25
+ end
26
+ end
27
+
28
+ end
@@ -354,18 +354,6 @@ class TestSimpleRecord < TestBase
354
354
  assert !o.nil?
355
355
  end
356
356
 
357
- # Use to populate db
358
- def create_my_models(count)
359
- batch = []
360
- count.times do |i|
361
- mm = MyModel.new(:name=>"model_" + i.to_s)
362
- batch << mm
363
- end
364
- MyModel.batch_save batch
365
-
366
-
367
- end
368
-
369
357
  def test_objects_in_constructor
370
358
  mm = MyModel.new(:name=>"model1")
371
359
  mm.save
@@ -586,7 +574,7 @@ class TestSimpleRecord < TestBase
586
574
  mm.update_attributes(:name=>"name2", :age=>21, "date2"=>now)
587
575
  assert mm.name == "name2", "Name is #{mm.name}"
588
576
  assert mm.age == 21
589
- assert mm.date2 == now
577
+ assert mm.date2.to_time.eql?(now), "#{mm.date2.class.name} #{mm.date2.to_time.inspect} != #{now.inspect}"
590
578
  sleep 1
591
579
 
592
580
  mm = MyModel.find(mm.id)
@@ -635,5 +623,48 @@ class TestSimpleRecord < TestBase
635
623
  mme = ModelWithEnc.new(:ssn=>nil, :password=>nil)
636
624
  end
637
625
 
626
+ def test_string_ints
627
+ mm = MyModel.new
628
+ mm.name = "whatever"
629
+ mm.age = "1"
630
+ puts mm.inspect
631
+
632
+ mm2 = MyModel.new
633
+ mm2.name = "whatever2"
634
+ mm2.age = 1
635
+ params = {:name=>"scooby", :age=>"123"}
636
+ mm3 = MyModel.new(params)
637
+
638
+
639
+ assert mm.age == 1, "mm.age=#{mm.age}"
640
+ assert mm2.age == 1
641
+ assert mm3.age == 123
642
+
643
+ mm.save!
644
+ mm2.save!
645
+ mm3.save!
646
+ sleep 1
647
+
648
+ assert mm.age == 1
649
+ assert mm2.age == 1
650
+ assert mm3.age == 123
651
+
652
+ mmf1 = MyModel.find(mm.id)
653
+ mmf2 = MyModel.find(mm2.id)
654
+ mmf3 = MyModel.find(mm3.id)
655
+
656
+ assert mmf1.age == 1
657
+ assert mmf2.age == 1
658
+ assert mmf3.age == 123
659
+
660
+ mmf1.update_attributes({:age=>"456"})
661
+
662
+ mmf1.age == 456
663
+
664
+
665
+
666
+
667
+
668
+ end
638
669
 
639
670
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.72
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 2
8
+ - 0
9
+ version: 1.2.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Travis Reeder
@@ -11,19 +16,21 @@ autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
18
 
14
- date: 2010-03-23 00:00:00 -07:00
19
+ date: 2010-05-01 00:00:00 -07:00
15
20
  default_executable:
16
21
  dependencies:
17
22
  - !ruby/object:Gem::Dependency
18
23
  name: aws
19
- type: :runtime
20
- version_requirement:
21
- version_requirements: !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
22
26
  requirements:
23
27
  - - ">="
24
28
  - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
25
31
  version: "0"
26
- version:
32
+ type: :runtime
33
+ version_requirements: *id001
27
34
  description: Drop in replacement for ActiveRecord to Amazon SimpleDB instead.
28
35
  email: travis@appoxy.com
29
36
  executables: []
@@ -38,6 +45,7 @@ files:
38
45
  - lib/simple_record/callbacks.rb
39
46
  - lib/simple_record/encryptor.rb
40
47
  - lib/simple_record/errors.rb
48
+ - lib/simple_record/exceptions.rb
41
49
  - lib/simple_record/password.rb
42
50
  - lib/simple_record/results_array.rb
43
51
  - lib/simple_record/stats.rb
@@ -56,33 +64,37 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
64
  requirements:
57
65
  - - ">="
58
66
  - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
59
69
  version: "0"
60
- version:
61
70
  required_rubygems_version: !ruby/object:Gem::Requirement
62
71
  requirements:
63
72
  - - ">="
64
73
  - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
65
76
  version: "0"
66
- version:
67
77
  requirements: []
68
78
 
69
79
  rubyforge_project:
70
- rubygems_version: 1.3.5
80
+ rubygems_version: 1.3.6
71
81
  signing_key:
72
82
  specification_version: 3
73
83
  summary: Drop in replacement for ActiveRecord to Amazon SimpleDB instead.
74
84
  test_files:
75
- - test/test_global_options.rb
76
- - test/temp_test.rb
77
- - test/test_dirty.rb
85
+ - test/conversions.rb
78
86
  - test/model_with_enc.rb
79
- - test/test_base.rb
80
- - test/my_model.rb
81
87
  - test/my_base_model.rb
88
+ - test/my_child_model.rb
89
+ - test/my_model.rb
82
90
  - test/paging_array_test.rb
83
- - test/test_simple_record.rb
91
+ - test/temp_test.rb
92
+ - test/test_base.rb
93
+ - test/test_dirty.rb
84
94
  - test/test_encodings.rb
95
+ - test/test_global_options.rb
85
96
  - test/test_helpers.rb
86
- - test/my_child_model.rb
97
+ - test/test_marshalled.rb
98
+ - test/test_pagination.rb
87
99
  - test/test_results_array.rb
88
- - test/conversions.rb
100
+ - test/test_simple_record.rb