dynamoid 0.0.2

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.
Files changed (54) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Dynamoid.gemspec +116 -0
  4. data/Gemfile +19 -0
  5. data/Gemfile.lock +58 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.markdown +86 -0
  8. data/Rakefile +49 -0
  9. data/VERSION +1 -0
  10. data/lib/dynamoid.rb +32 -0
  11. data/lib/dynamoid/adapter.rb +24 -0
  12. data/lib/dynamoid/adapter/aws_sdk.rb +100 -0
  13. data/lib/dynamoid/adapter/local.rb +77 -0
  14. data/lib/dynamoid/associations.rb +54 -0
  15. data/lib/dynamoid/associations/association.rb +80 -0
  16. data/lib/dynamoid/associations/belongs_to.rb +39 -0
  17. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +34 -0
  18. data/lib/dynamoid/associations/has_many.rb +33 -0
  19. data/lib/dynamoid/associations/has_one.rb +36 -0
  20. data/lib/dynamoid/attributes.rb +37 -0
  21. data/lib/dynamoid/components.rb +25 -0
  22. data/lib/dynamoid/config.rb +19 -0
  23. data/lib/dynamoid/config/options.rb +74 -0
  24. data/lib/dynamoid/document.rb +35 -0
  25. data/lib/dynamoid/errors.rb +8 -0
  26. data/lib/dynamoid/fields.rb +32 -0
  27. data/lib/dynamoid/finders.rb +62 -0
  28. data/lib/dynamoid/indexes.rb +59 -0
  29. data/lib/dynamoid/persistence.rb +35 -0
  30. data/lib/dynamoid/relations.rb +21 -0
  31. data/spec/app/models/address.rb +5 -0
  32. data/spec/app/models/magazine.rb +6 -0
  33. data/spec/app/models/sponsor.rb +6 -0
  34. data/spec/app/models/subscription.rb +6 -0
  35. data/spec/app/models/user.rb +13 -0
  36. data/spec/dynamoid/adapter/aws_sdk_spec.rb +123 -0
  37. data/spec/dynamoid/adapter/local_spec.rb +150 -0
  38. data/spec/dynamoid/adapter_spec.rb +13 -0
  39. data/spec/dynamoid/associations/association_spec.rb +71 -0
  40. data/spec/dynamoid/associations/belongs_to_spec.rb +50 -0
  41. data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +30 -0
  42. data/spec/dynamoid/associations/has_many_spec.rb +28 -0
  43. data/spec/dynamoid/associations/has_one_spec.rb +37 -0
  44. data/spec/dynamoid/associations_spec.rb +16 -0
  45. data/spec/dynamoid/attributes_spec.rb +43 -0
  46. data/spec/dynamoid/document_spec.rb +38 -0
  47. data/spec/dynamoid/fields_spec.rb +26 -0
  48. data/spec/dynamoid/finders_spec.rb +114 -0
  49. data/spec/dynamoid/indexes_spec.rb +54 -0
  50. data/spec/dynamoid/persistence_spec.rb +55 -0
  51. data/spec/dynamoid/relations_spec.rb +6 -0
  52. data/spec/dynamoid_spec.rb +5 -0
  53. data/spec/spec_helper.rb +52 -0
  54. metadata +204 -0
@@ -0,0 +1,150 @@
1
+ require 'dynamoid/adapter/local'
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ describe Dynamoid::Adapter::Local do
5
+
6
+ unless ENV['ACCESS_KEY'] && ENV['SECRET_KEY']
7
+
8
+ # BatchGetItem
9
+ it 'performs BatchGetItem with singular keys' do
10
+ Dynamoid::Adapter.create_table('table1', :id)
11
+ Dynamoid::Adapter.put_item('table1', {:id => '1', :name => 'Josh'})
12
+ Dynamoid::Adapter.create_table('table2', :id)
13
+ Dynamoid::Adapter.put_item('table2', {:id => '1', :name => 'Justin'})
14
+
15
+ results = Dynamoid::Adapter.batch_get_item('table1' => '1', 'table2' => '1')
16
+ results.size.should == 2
17
+ results['table1'].should include({:name => 'Josh', :id => '1'})
18
+ results['table2'].should include({:name => 'Justin', :id => '1'})
19
+ end
20
+
21
+ it 'performs BatchGetItem with multiple keys' do
22
+ Dynamoid::Adapter.create_table('table1', :id)
23
+ Dynamoid::Adapter.put_item('table1', {:id => '1', :name => 'Josh'})
24
+ Dynamoid::Adapter.put_item('table1', {:id => '2', :name => 'Justin'})
25
+
26
+ results = Dynamoid::Adapter.batch_get_item('table1' => ['1', '2'])
27
+ results.size.should == 1
28
+ results['table1'].should include({:name => 'Josh', :id => '1'})
29
+ results['table1'].should include({:name => 'Justin', :id => '2'})
30
+ end
31
+
32
+ # CreateTable
33
+ it 'performs CreateTable' do
34
+ Dynamoid::Adapter.create_table('Test Table', :id)
35
+
36
+ Dynamoid::Adapter.list_tables.should include 'Test Table'
37
+ end
38
+
39
+ # DeleteItem
40
+ it 'performs DeleteItem' do
41
+ Dynamoid::Adapter.create_table('table1', :id)
42
+ Dynamoid::Adapter.put_item('table1', {:id => '1', :name => 'Josh'})
43
+
44
+ Dynamoid::Adapter.delete_item('table1', '1')
45
+
46
+ Dynamoid::Adapter.data['table1'][:data].should be_empty
47
+ end
48
+
49
+ it 'performs DeleteItem for an item that does not exist' do
50
+ Dynamoid::Adapter.create_table('table1', :id)
51
+
52
+ Dynamoid::Adapter.delete_item('table1', '1')
53
+
54
+ Dynamoid::Adapter.data['table1'][:data].should be_empty
55
+ end
56
+
57
+ # DeleteTable
58
+ it 'performs DeleteTable' do
59
+ Dynamoid::Adapter.create_table('table1', :id)
60
+
61
+ Dynamoid::Adapter.delete_table('table1')
62
+
63
+ Dynamoid::Adapter.data['table1'].should be_nil
64
+ end
65
+
66
+ # DescribeTable
67
+
68
+ # GetItem
69
+ it "performs GetItem for an item that does not exist" do
70
+ Dynamoid::Adapter.create_table('Test Table', :id)
71
+
72
+ Dynamoid::Adapter.get_item('Test Table', '1').should be_nil
73
+ end
74
+
75
+ it "performs GetItem for an item that does exist" do
76
+ Dynamoid::Adapter.create_table('Test Table', :id)
77
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
78
+
79
+ Dynamoid::Adapter.get_item('Test Table', '1').should == {:id => '1', :name => 'Josh'}
80
+ end
81
+
82
+ # ListTables
83
+ it 'performs ListTables' do
84
+ Dynamoid::Adapter.create_table('Table1', :id)
85
+ Dynamoid::Adapter.create_table('Table2', :id)
86
+
87
+ Dynamoid::Adapter.list_tables.should include 'Table1'
88
+ Dynamoid::Adapter.list_tables.should include 'Table2'
89
+ end
90
+
91
+ # PutItem
92
+ it 'performs PutItem for an item that does not exist' do
93
+ Dynamoid::Adapter.create_table('Test Table', :id)
94
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
95
+
96
+ Dynamoid::Adapter.data['Test Table'].should == { :id => :id, :data => { '1' => { :id=> '1', :name=>"Josh" }}}
97
+ end
98
+
99
+ # Query
100
+ it 'performs query on a table and returns items' do
101
+ Dynamoid::Adapter.create_table('Test Table', :id)
102
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
103
+
104
+ Dynamoid::Adapter.query('Test Table', '1').should == { :id=> '1', :name=>"Josh" }
105
+ end
106
+
107
+ it 'performs query on a table and returns items if there are multiple items' do
108
+ Dynamoid::Adapter.create_table('Test Table', :id)
109
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
110
+ Dynamoid::Adapter.put_item('Test Table', {:id => '2', :name => 'Justin'})
111
+
112
+ Dynamoid::Adapter.query('Test Table', '1').should == { :id=> '1', :name=>"Josh" }
113
+ end
114
+
115
+ # Scan
116
+ it 'performs scan on a table and returns items' do
117
+ Dynamoid::Adapter.create_table('Test Table', :id)
118
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
119
+
120
+ Dynamoid::Adapter.scan('Test Table', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
121
+ end
122
+
123
+ it 'performs scan on a table and returns items if there are multiple items but only one match' do
124
+ Dynamoid::Adapter.create_table('Test Table', :id)
125
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
126
+ Dynamoid::Adapter.put_item('Test Table', {:id => '2', :name => 'Justin'})
127
+
128
+ Dynamoid::Adapter.scan('Test Table', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
129
+ end
130
+
131
+ it 'performs scan on a table and returns multiple items if there are multiple matches' do
132
+ Dynamoid::Adapter.create_table('Test Table', :id)
133
+ Dynamoid::Adapter.put_item('Test Table', {:id => '1', :name => 'Josh'})
134
+ Dynamoid::Adapter.put_item('Test Table', {:id => '2', :name => 'Josh'})
135
+
136
+ Dynamoid::Adapter.scan('Test Table', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }, { :id=> '2', :name=>"Josh" }]
137
+ end
138
+
139
+ # UpdateItem
140
+
141
+ # UpdateTable
142
+
143
+ protected
144
+
145
+ def setup_value(table, key, value)
146
+ Dynamoid::Adapter.data[table][key] = value
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Adapter" do
4
+
5
+ it 'extends itself automatically' do
6
+ lambda {Dynamoid::Adapter.list_tables}.should_not raise_error
7
+ end
8
+
9
+ it 'raises nomethod if we try a method that is not on the child' do
10
+ lambda {Dynamoid::Adapter.foobar}.should raise_error
11
+ end
12
+
13
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "Dynamoid::Associations::Association" do
4
+
5
+ before do
6
+ @magazine = Magazine.create
7
+ end
8
+
9
+ it 'returns an empty array if there are no associations' do
10
+ @magazine.subscriptions.should be_empty
11
+ end
12
+
13
+ it 'adds an item to an association' do
14
+ @subscription = Subscription.create
15
+
16
+ @magazine.subscriptions << @subscription
17
+ @magazine.subscriptions.size.should == 1
18
+ @magazine.subscriptions.should include @subscription
19
+ end
20
+
21
+ it 'deletes an item from an association' do
22
+ @subscription = Subscription.create
23
+ @magazine.subscriptions << @subscription
24
+
25
+ @magazine.subscriptions.delete(@subscription)
26
+ @magazine.subscriptions.size.should == 0
27
+ end
28
+
29
+ it 'creates an item from an association' do
30
+ @subscription = @magazine.subscriptions.create
31
+
32
+ @subscription.class.should == Subscription
33
+ @magazine.subscriptions.size.should == 1
34
+ @magazine.subscriptions.should include @subscription
35
+ end
36
+
37
+ it 'returns the number of items in the association' do
38
+ @magazine.subscriptions.create
39
+
40
+ @magazine.subscriptions.size.should == 1
41
+
42
+ @magazine.subscriptions.create
43
+
44
+ @magazine.subscriptions.size.should == 2
45
+ end
46
+
47
+ it 'assigns directly via the equals operator' do
48
+ @subscription = Subscription.create
49
+ @magazine.subscriptions = [@subscription]
50
+
51
+ @magazine.subscriptions.should == [@subscription]
52
+ end
53
+
54
+ it 'assigns directly via the equals operator and reflects to the target association' do
55
+ @subscription = Subscription.create
56
+ @magazine.subscriptions = [@subscription]
57
+
58
+ @subscription.magazine.should == @magazine
59
+ end
60
+
61
+ it 'does not assign reflection association if the reflection association does not exist' do
62
+ @sponsor = Sponsor.create
63
+
64
+ @subscription = @sponsor.subscriptions.create
65
+ @subscription.should_not respond_to :sponsor
66
+ @subscription.should_not respond_to :sponsors
67
+ @subscription.should_not respond_to :sponsors_ids
68
+ @subscription.should_not respond_to :sponsor_ids
69
+ end
70
+
71
+ end
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "Dynamoid::Associations::BelongsTo" do
4
+
5
+ context 'has many' do
6
+ before do
7
+ @subscription = Subscription.create
8
+ end
9
+
10
+ it 'determins nil if it has no associated record' do
11
+ @subscription.magazine.should be_nil
12
+ end
13
+
14
+ it 'delegates equality to its source record' do
15
+ @magazine = @subscription.magazine.create
16
+
17
+ @subscription.magazine.should == @magazine
18
+ end
19
+
20
+ it 'associates has_many automatically' do
21
+ @magazine = @subscription.magazine.create
22
+
23
+ @magazine.subscriptions.size.should == 1
24
+ @magazine.subscriptions.should include @subscription
25
+ end
26
+ end
27
+
28
+ context 'has one' do
29
+ before do
30
+ @sponsor = Sponsor.create
31
+ end
32
+
33
+ it 'determins nil if it has no associated record' do
34
+ @sponsor.magazine.should be_nil
35
+ end
36
+
37
+ it 'delegates equality to its source record' do
38
+ @magazine = @sponsor.magazine.create
39
+
40
+ @sponsor.magazine.should == @magazine
41
+ end
42
+
43
+ it 'associates has_one automatically' do
44
+ @magazine = @sponsor.magazine.create
45
+
46
+ @magazine.sponsor.size.should == 1
47
+ @magazine.sponsor.should == @sponsor
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "Dynamoid::Associations::HasAndBelongsToMany" do
4
+
5
+ before do
6
+ @subscription = Subscription.create
7
+ end
8
+
9
+ it 'determines equality from its records' do
10
+ @user = @subscription.users.create
11
+
12
+ @subscription.users.size.should == 1
13
+ @subscription.users.should include @user
14
+ end
15
+
16
+ it 'determines target association correctly' do
17
+ @subscription.users.send(:target_association).should == :subscriptions
18
+ end
19
+
20
+ it 'determines target attribute' do
21
+ @subscription.users.send(:target_attribute).should == :subscriptions_ids
22
+ end
23
+
24
+ it 'associates has_and_belongs_to_many automatically' do
25
+ @user = @subscription.users.create
26
+
27
+ @user.subscriptions.size.should == 1
28
+ @user.subscriptions.should include @subscription
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "Dynamoid::Associations::HasMany" do
4
+
5
+ before do
6
+ @magazine = Magazine.create
7
+ end
8
+
9
+ it 'determines equality from its records' do
10
+ @subscription = @magazine.subscriptions.create
11
+
12
+ @magazine.subscriptions.should == @subscription
13
+ end
14
+
15
+ it 'determines target association correctly' do
16
+ @magazine.subscriptions.send(:target_association).should == :magazine
17
+ end
18
+
19
+ it 'determines target attribute' do
20
+ @magazine.subscriptions.send(:target_attribute).should == :magazine_ids
21
+ end
22
+
23
+ it 'associates belongs_to automatically' do
24
+ @subscription = @magazine.subscriptions.create
25
+
26
+ @subscription.magazine.should == @magazine
27
+ end
28
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "Dynamoid::Associations::HasOne" do
4
+
5
+ before do
6
+ @magazine = Magazine.create
7
+ end
8
+
9
+ it 'determines nil if it has no associated record' do
10
+ @magazine.sponsor.should be_nil
11
+ end
12
+
13
+ it 'returns only one object when associated' do
14
+ @magazine.sponsor.create
15
+
16
+ @magazine.sponsor.should_not be_a_kind_of Array
17
+ end
18
+
19
+ it 'delegates equality to its source record' do
20
+ @sponsor = @magazine.sponsor.create
21
+
22
+ @magazine.sponsor.should == @sponsor
23
+ end
24
+
25
+ it 'is equal from its target record' do
26
+ @sponsor = @magazine.sponsor.create
27
+
28
+ @magazine.sponsor.should == @sponsor
29
+ end
30
+
31
+ it 'associates belongs_to automatically' do
32
+ @sponsor = @magazine.sponsor.create
33
+
34
+ @magazine.sponsor.size.should == 1
35
+ @magazine.sponsor.should == @sponsor
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Associations" do
4
+
5
+ before do
6
+ @magazine = Magazine.create
7
+ end
8
+
9
+ it 'defines a getter' do
10
+ @magazine.should respond_to :subscriptions
11
+ end
12
+
13
+ it 'defines a setter' do
14
+ @magazine.should respond_to :subscriptions=
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Attributes" do
4
+
5
+ before do
6
+ @address = Address.new
7
+ end
8
+
9
+ it 'should write an attribute correctly' do
10
+ @address.write_attribute(:city, 'Chicago')
11
+ end
12
+
13
+ it 'should write an attribute with the alias' do
14
+ @address[:city] = 'Chicago'
15
+ end
16
+
17
+ it 'should read a written attribute' do
18
+ @address.write_attribute(:city, 'Chicago')
19
+ @address.read_attribute(:city).should == 'Chicago'
20
+ end
21
+
22
+ it 'should read a written attribute with the alias' do
23
+ @address.write_attribute(:city, 'Chicago')
24
+ @address[:city].should == 'Chicago'
25
+ end
26
+
27
+ it 'should update all attributes' do
28
+ @address.expects(:save).once.returns(true)
29
+ @address.update_attributes(:city => 'Chicago')
30
+ @address[:city].should == 'Chicago'
31
+ end
32
+
33
+ it 'should update one attribute' do
34
+ @address.expects(:save).once.returns(true)
35
+ @address.update_attribute(:city, 'Chicago')
36
+ @address[:city].should == 'Chicago'
37
+ end
38
+
39
+ it 'returns all attributes' do
40
+ Address.attributes.should == [:id, :city]
41
+ end
42
+
43
+ end