simple_record 1.1.72 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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