dynamoid 0.7.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +2 -24
  3. data/README.markdown +89 -73
  4. data/Rakefile +10 -36
  5. data/dynamoid.gemspec +56 -191
  6. data/lib/dynamoid.rb +6 -4
  7. data/lib/dynamoid/adapter.rb +64 -150
  8. data/lib/dynamoid/adapter_plugin/aws_sdk_v2.rb +579 -0
  9. data/lib/dynamoid/components.rb +0 -1
  10. data/lib/dynamoid/config.rb +2 -5
  11. data/lib/dynamoid/criteria.rb +1 -1
  12. data/lib/dynamoid/criteria/chain.rb +27 -140
  13. data/lib/dynamoid/document.rb +2 -2
  14. data/lib/dynamoid/errors.rb +30 -9
  15. data/lib/dynamoid/fields.rb +15 -3
  16. data/lib/dynamoid/finders.rb +7 -6
  17. data/lib/dynamoid/identity_map.rb +1 -5
  18. data/lib/dynamoid/persistence.rb +108 -93
  19. metadata +56 -229
  20. data/.document +0 -5
  21. data/.rspec +0 -1
  22. data/.travis.yml +0 -7
  23. data/Gemfile.lock +0 -81
  24. data/Gemfile_activemodel4 +0 -24
  25. data/Gemfile_activemodel4.lock +0 -88
  26. data/VERSION +0 -1
  27. data/doc/.nojekyll +0 -0
  28. data/doc/Dynamoid.html +0 -328
  29. data/doc/Dynamoid/Adapter.html +0 -1872
  30. data/doc/Dynamoid/Adapter/AwsSdk.html +0 -2101
  31. data/doc/Dynamoid/Adapter/Local.html +0 -1574
  32. data/doc/Dynamoid/Associations.html +0 -138
  33. data/doc/Dynamoid/Associations/Association.html +0 -847
  34. data/doc/Dynamoid/Associations/BelongsTo.html +0 -161
  35. data/doc/Dynamoid/Associations/ClassMethods.html +0 -766
  36. data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +0 -167
  37. data/doc/Dynamoid/Associations/HasMany.html +0 -167
  38. data/doc/Dynamoid/Associations/HasOne.html +0 -161
  39. data/doc/Dynamoid/Associations/ManyAssociation.html +0 -1684
  40. data/doc/Dynamoid/Associations/SingleAssociation.html +0 -627
  41. data/doc/Dynamoid/Components.html +0 -242
  42. data/doc/Dynamoid/Config.html +0 -412
  43. data/doc/Dynamoid/Config/Options.html +0 -638
  44. data/doc/Dynamoid/Criteria.html +0 -138
  45. data/doc/Dynamoid/Criteria/Chain.html +0 -1471
  46. data/doc/Dynamoid/Criteria/ClassMethods.html +0 -105
  47. data/doc/Dynamoid/Dirty.html +0 -424
  48. data/doc/Dynamoid/Dirty/ClassMethods.html +0 -174
  49. data/doc/Dynamoid/Document.html +0 -1033
  50. data/doc/Dynamoid/Document/ClassMethods.html +0 -1116
  51. data/doc/Dynamoid/Errors.html +0 -125
  52. data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +0 -141
  53. data/doc/Dynamoid/Errors/DocumentNotValid.html +0 -221
  54. data/doc/Dynamoid/Errors/Error.html +0 -137
  55. data/doc/Dynamoid/Errors/InvalidField.html +0 -141
  56. data/doc/Dynamoid/Errors/InvalidQuery.html +0 -131
  57. data/doc/Dynamoid/Errors/MissingRangeKey.html +0 -141
  58. data/doc/Dynamoid/Fields.html +0 -686
  59. data/doc/Dynamoid/Fields/ClassMethods.html +0 -438
  60. data/doc/Dynamoid/Finders.html +0 -135
  61. data/doc/Dynamoid/Finders/ClassMethods.html +0 -943
  62. data/doc/Dynamoid/IdentityMap.html +0 -492
  63. data/doc/Dynamoid/IdentityMap/ClassMethods.html +0 -534
  64. data/doc/Dynamoid/Indexes.html +0 -321
  65. data/doc/Dynamoid/Indexes/ClassMethods.html +0 -369
  66. data/doc/Dynamoid/Indexes/Index.html +0 -1142
  67. data/doc/Dynamoid/Middleware.html +0 -115
  68. data/doc/Dynamoid/Middleware/IdentityMap.html +0 -264
  69. data/doc/Dynamoid/Persistence.html +0 -892
  70. data/doc/Dynamoid/Persistence/ClassMethods.html +0 -836
  71. data/doc/Dynamoid/Validations.html +0 -415
  72. data/doc/_index.html +0 -506
  73. data/doc/class_list.html +0 -53
  74. data/doc/css/common.css +0 -1
  75. data/doc/css/full_list.css +0 -57
  76. data/doc/css/style.css +0 -338
  77. data/doc/file.LICENSE.html +0 -73
  78. data/doc/file.README.html +0 -416
  79. data/doc/file_list.html +0 -58
  80. data/doc/frames.html +0 -28
  81. data/doc/index.html +0 -416
  82. data/doc/js/app.js +0 -214
  83. data/doc/js/full_list.js +0 -178
  84. data/doc/js/jquery.js +0 -4
  85. data/doc/method_list.html +0 -1144
  86. data/doc/top-level-namespace.html +0 -112
  87. data/lib/dynamoid/adapter/aws_sdk.rb +0 -287
  88. data/lib/dynamoid/indexes.rb +0 -69
  89. data/lib/dynamoid/indexes/index.rb +0 -103
  90. data/spec/app/models/address.rb +0 -13
  91. data/spec/app/models/camel_case.rb +0 -34
  92. data/spec/app/models/car.rb +0 -6
  93. data/spec/app/models/magazine.rb +0 -11
  94. data/spec/app/models/message.rb +0 -9
  95. data/spec/app/models/nuclear_submarine.rb +0 -5
  96. data/spec/app/models/sponsor.rb +0 -8
  97. data/spec/app/models/subscription.rb +0 -12
  98. data/spec/app/models/tweet.rb +0 -12
  99. data/spec/app/models/user.rb +0 -26
  100. data/spec/app/models/vehicle.rb +0 -7
  101. data/spec/dynamoid/adapter/aws_sdk_spec.rb +0 -376
  102. data/spec/dynamoid/adapter_spec.rb +0 -155
  103. data/spec/dynamoid/associations/association_spec.rb +0 -194
  104. data/spec/dynamoid/associations/belongs_to_spec.rb +0 -71
  105. data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +0 -47
  106. data/spec/dynamoid/associations/has_many_spec.rb +0 -42
  107. data/spec/dynamoid/associations/has_one_spec.rb +0 -45
  108. data/spec/dynamoid/associations_spec.rb +0 -16
  109. data/spec/dynamoid/config_spec.rb +0 -27
  110. data/spec/dynamoid/criteria/chain_spec.rb +0 -210
  111. data/spec/dynamoid/criteria_spec.rb +0 -75
  112. data/spec/dynamoid/dirty_spec.rb +0 -57
  113. data/spec/dynamoid/document_spec.rb +0 -180
  114. data/spec/dynamoid/fields_spec.rb +0 -156
  115. data/spec/dynamoid/finders_spec.rb +0 -147
  116. data/spec/dynamoid/identity_map_spec.rb +0 -45
  117. data/spec/dynamoid/indexes/index_spec.rb +0 -104
  118. data/spec/dynamoid/indexes_spec.rb +0 -25
  119. data/spec/dynamoid/persistence_spec.rb +0 -301
  120. data/spec/dynamoid/validations_spec.rb +0 -36
  121. data/spec/dynamoid_spec.rb +0 -9
  122. data/spec/spec_helper.rb +0 -55
  123. data/spec/support/with_partitioning.rb +0 -15
@@ -1,155 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe Dynamoid::Adapter do
4
-
5
- def test_table; 'dynamoid_tests_TestTable'; end
6
- let(:single_id){'123'}
7
- let(:many_ids){%w(1 2)}
8
-
9
- before(:all) do
10
- described_class.create_table(test_table, :id) unless described_class.list_tables.include?(test_table)
11
- end
12
-
13
- it 'extends itself automatically' do
14
- lambda {described_class.list_tables}.should_not raise_error
15
- end
16
-
17
- it 'raises NoMethodError if we try a method that is not on the child' do
18
- lambda {described_class.foobar}.should raise_error(NoMethodError)
19
- end
20
-
21
- context 'without partioning' do
22
- before(:all) do
23
- @previous_value = Dynamoid::Config.partitioning
24
- Dynamoid::Config.partitioning = false
25
- end
26
-
27
- after(:all) do
28
- Dynamoid::Config.partitioning = @previous_value
29
- end
30
-
31
- it 'writes through the adapter' do
32
- described_class.expects(:put_item).with(test_table, {:id => single_id}, nil).returns(true)
33
- described_class.write(test_table, {:id => single_id})
34
- end
35
-
36
- it 'reads through the adapter for one ID' do
37
- described_class.expects(:get_item).with(test_table, single_id, {}).returns(true)
38
- described_class.read(test_table, single_id)
39
- end
40
-
41
- it 'reads through the adapter for many IDs' do
42
- described_class.expects(:batch_get_item).with({test_table => many_ids}, {}).returns(true)
43
- described_class.read(test_table, many_ids)
44
- end
45
-
46
- it 'delete through the adapter for one ID' do
47
- described_class.expects(:delete_item).with(test_table, single_id, {}).returns(nil)
48
- described_class.delete(test_table, single_id)
49
- end
50
-
51
- it 'deletes through the adapter for many IDs' do
52
- described_class.expects(:batch_delete_item).with({test_table => many_ids}).returns(nil)
53
- described_class.delete(test_table, many_ids)
54
- end
55
-
56
- it 'reads through the adapter for one ID and a range key' do
57
- described_class.expects(:get_item).with(test_table, single_id, :range_key => 2.0).returns(true)
58
- described_class.read(test_table, single_id, :range_key => 2.0)
59
- end
60
-
61
- it 'reads through the adapter for many IDs and a range key' do
62
- described_class.expects(:batch_get_item).with({test_table => [['1', 2.0], ['2', 2.0]]}, {}).returns(true)
63
- described_class.read(test_table, many_ids, :range_key => 2.0)
64
- end
65
-
66
- it 'deletes through the adapter for one ID and a range key' do
67
- described_class.expects(:delete_item).with(test_table, single_id, :range_key => 2.0).returns(nil)
68
- described_class.delete(test_table, single_id, :range_key => 2.0)
69
- end
70
-
71
- it 'deletes through the adapter for many IDs and a range key' do
72
- described_class.expects(:batch_delete_item).with({test_table => [['1', 2.0], ['2', 2.0]]}).returns(nil)
73
- described_class.delete(test_table, many_ids, :range_key => [2.0,2.0])
74
- end
75
- end
76
-
77
- configured_with 'partitioning' do
78
- let(:partition_range){0...Dynamoid::Config.partition_size}
79
-
80
- it 'writes through the adapter' do
81
- Random.expects(:rand).with(Dynamoid::Config.partition_size).once.returns(0)
82
- described_class.write(test_table, {:id => 'testid'})
83
-
84
- described_class.get_item(test_table, 'testid.0')[:id].should == 'testid.0'
85
- described_class.get_item(test_table, 'testid.0')[:updated_at].should_not be_nil
86
- end
87
-
88
- it 'reads through the adapter for one ID' do
89
- described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| "123.#{n}"}}, {}).returns({})
90
- described_class.read(test_table, single_id)
91
- end
92
-
93
- it 'reads through the adapter for many IDs' do
94
- described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| "1.#{n}"} + partition_range.map{|n| "2.#{n}"}}, {}).returns({})
95
- described_class.read(test_table, many_ids)
96
- end
97
-
98
- it 'reads through the adapter for one ID and a range key' do
99
- described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| ["123.#{n}", 2.0]}}, {}).returns({})
100
- described_class.read(test_table, single_id, :range_key => 2.0)
101
- end
102
-
103
- it 'reads through the adapter for many IDs and a range key' do
104
- described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| ["1.#{n}", 2.0]} + partition_range.map{|n| ["2.#{n}", 2.0]}}, {}).returns({})
105
- described_class.read(test_table, many_ids, :range_key => 2.0)
106
- end
107
-
108
- it 'returns an ID with all partitions' do
109
- described_class.id_with_partitions('1').should =~ partition_range.map{|n| "1.#{n}"}
110
- end
111
-
112
- it 'returns an ID and range key with all partitions' do
113
- described_class.id_with_partitions([['1', 1.0]]).should =~ partition_range.map{|n| ["1.#{n}", 1.0]}
114
- end
115
-
116
- it 'returns a result for one partitioned element' do
117
- @time = DateTime.now
118
- @array =[{:id => '1.0', :updated_at => @time - 6.hours},
119
- {:id => '1.1', :updated_at => @time - 3.hours},
120
- {:id => '1.2', :updated_at => @time - 1.hour},
121
- {:id => '1.3', :updated_at => @time - 6.hours},
122
- {:id => '2.0', :updated_at => @time}]
123
-
124
- described_class.result_for_partition(@array,test_table).should =~ [{:id => '1', :updated_at => @time - 1.hour},
125
- {:id => '2', :updated_at => @time}]
126
- end
127
-
128
- it 'returns a valid original id and partition number' do
129
- @id = "12345.387327.-sdf3"
130
- @partition_number = "4"
131
- described_class.get_original_id_and_partition("#{@id}.#{@partition_number}").should == [@id, @partition_number]
132
- end
133
-
134
- it 'delete through the adapter for one ID' do
135
- described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| "123.#{n}"}).returns(nil)
136
- described_class.delete(test_table, single_id)
137
- end
138
-
139
- it 'deletes through the adapter for many IDs' do
140
- described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| "1.#{n}"} + partition_range.map{|n| "2.#{n}"}).returns(nil)
141
- described_class.delete(test_table, many_ids)
142
- end
143
-
144
- it 'deletes through the adapter for one ID and a range key' do
145
- described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| ["123.#{n}", 2.0]}).returns(nil)
146
- described_class.delete(test_table, single_id, :range_key => 2.0)
147
- end
148
-
149
- it 'deletes through the adapter for many IDs and a range key' do
150
- described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| ["1.#{n}", 2.0]} + partition_range.map{|n| ["2.#{n}", 2.0]}).returns(nil)
151
- described_class.delete(test_table, many_ids, :range_key => [2.0,2.0])
152
- end
153
- end
154
-
155
- end
@@ -1,194 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe "Dynamoid::Associations::Association" do
4
-
5
- before do
6
- Subscription.create_table
7
- @magazine = Magazine.create
8
- end
9
-
10
- it 'returns an empty array if there are no associations' do
11
- @magazine.subscriptions.should be_empty
12
- end
13
-
14
- it 'adds an item to an association' do
15
- @subscription = Subscription.create
16
-
17
- @magazine.subscriptions << @subscription
18
- @magazine.subscriptions.size.should == 1
19
- @magazine.subscriptions.should include @subscription
20
- end
21
-
22
- it 'deletes an item from an association' do
23
- @subscription = Subscription.create
24
- @magazine.subscriptions << @subscription
25
-
26
- @magazine.subscriptions.delete(@subscription)
27
- @magazine.subscriptions.size.should == 0
28
- end
29
-
30
- it 'creates an item from an association' do
31
- @subscription = @magazine.subscriptions.create
32
-
33
- @subscription.class.should == Subscription
34
- @magazine.subscriptions.size.should == 1
35
- @magazine.subscriptions.should include @subscription
36
- end
37
-
38
- it 'returns the number of items in the association' do
39
- @magazine.subscriptions.create
40
- @magazine.subscriptions.size.should == 1
41
-
42
- @second = @magazine.subscriptions.create
43
- @magazine.subscriptions.size.should == 2
44
-
45
- @magazine.subscriptions.delete(@second)
46
- @magazine.subscriptions.size.should == 1
47
-
48
- @magazine.subscriptions = []
49
- @magazine.subscriptions.size.should == 0
50
- end
51
-
52
- it 'assigns directly via the equals operator' do
53
- @subscription = Subscription.create
54
- @magazine.subscriptions = [@subscription]
55
-
56
- @magazine.subscriptions.should == [@subscription]
57
- end
58
-
59
- it 'assigns directly via the equals operator and reflects to the target association' do
60
- @subscription = Subscription.create
61
- @magazine.subscriptions = [@subscription]
62
-
63
- @subscription.magazine.should == @magazine
64
- end
65
-
66
- it 'does not assign reflection association if the reflection association does not exist' do
67
- @sponsor = Sponsor.create
68
-
69
- @subscription = @sponsor.subscriptions.create
70
- @subscription.should_not respond_to :sponsor
71
- @subscription.should_not respond_to :sponsors
72
- @subscription.should_not respond_to :sponsors_ids
73
- @subscription.should_not respond_to :sponsor_ids
74
- end
75
-
76
- it 'deletes all items from the association' do
77
- @magazine.subscriptions << Subscription.create
78
- @magazine.subscriptions << Subscription.create
79
- @magazine.subscriptions << Subscription.create
80
-
81
- @magazine.subscriptions.size.should == 3
82
-
83
- @magazine.subscriptions = nil
84
- @magazine.subscriptions.size.should == 0
85
- end
86
-
87
- it 'uses where inside an association and returns a result' do
88
- @included_subscription = @magazine.subscriptions.create(:length => 10)
89
- @unincldued_subscription = @magazine.subscriptions.create(:length => 8)
90
-
91
- @magazine.subscriptions.where(:length => 10).all.should == [@included_subscription]
92
- end
93
-
94
- it 'uses where inside an association and returns an empty set' do
95
- @included_subscription = @magazine.subscriptions.create(:length => 10)
96
- @unincldued_subscription = @magazine.subscriptions.create(:length => 8)
97
-
98
- @magazine.subscriptions.where(:length => 6).all.should be_empty
99
- end
100
-
101
- it 'includes enumerable' do
102
- @subscription1 = @magazine.subscriptions.create
103
- @subscription2 = @magazine.subscriptions.create
104
- @subscription3 = @magazine.subscriptions.create
105
-
106
- @magazine.subscriptions.collect(&:id).should =~ [@subscription1.id, @subscription2.id, @subscription3.id]
107
- end
108
-
109
- it 'works for camel-cased associations' do
110
- @magazine.camel_cases.create.class.should == CamelCase
111
- end
112
-
113
- it 'destroys associations' do
114
- @subscription = Subscription.new
115
- @magazine.subscriptions.expects(:target).returns([@subscription])
116
- @subscription.expects(:destroy)
117
-
118
- @magazine.subscriptions.destroy_all
119
- end
120
-
121
- it 'deletes associations' do
122
- @subscription = Subscription.new
123
- @magazine.subscriptions.expects(:target).returns([@subscription])
124
- @subscription.expects(:delete)
125
-
126
- @magazine.subscriptions.delete_all
127
- end
128
-
129
- # TODO This test is broken using the AWS SDK adapter.
130
- #it 'returns the first and last record when they exist' do
131
- # @subscription1 = @magazine.subscriptions.create
132
- # @subscription2 = @magazine.subscriptions.create
133
- # @subscription3 = @magazine.subscriptions.create
134
- #
135
- # @magazine.subscriptions.instance_eval { [first, last] }.should == [@subscription1, @subscription3]
136
- #end
137
-
138
- it 'replaces existing associations when using the setter' do
139
- @subscription1 = @magazine.subscriptions.create
140
- @subscription2 = @magazine.subscriptions.create
141
- @subscription3 = Subscription.create
142
-
143
- @subscription1.reload.magazine_ids.should_not be_nil
144
- @subscription2.reload.magazine_ids.should_not be_nil
145
-
146
- @magazine.subscriptions = @subscription3
147
- @magazine.subscriptions_ids.should == Set[@subscription3.id]
148
-
149
- @subscription1.reload.magazine_ids.should be_nil
150
- @subscription2.reload.magazine_ids.should be_nil
151
- @subscription3.reload.magazine_ids.should == Set[@magazine.id]
152
- end
153
-
154
- it 'destroys all objects and removes them from the association' do
155
- @subscription1 = @magazine.subscriptions.create
156
- @subscription2 = @magazine.subscriptions.create
157
- @subscription3 = @magazine.subscriptions.create
158
-
159
- @magazine.subscriptions.destroy_all
160
-
161
- @magazine.subscriptions.should be_empty
162
- Subscription.all.should be_empty
163
- end
164
-
165
- it 'deletes all objects and removes them from the association' do
166
- @subscription1 = @magazine.subscriptions.create
167
- @subscription2 = @magazine.subscriptions.create
168
- @subscription3 = @magazine.subscriptions.create
169
-
170
- @magazine.subscriptions.delete_all
171
-
172
- @magazine.subscriptions.should be_empty
173
- Subscription.all.should be_empty
174
- end
175
-
176
- it 'delegates class to the association object' do
177
- @magazine.sponsor.class.should == nil.class
178
- @magazine.sponsor.create
179
- @magazine.sponsor.class.should == Sponsor
180
-
181
- @magazine.subscriptions.class.should == Array
182
- @magazine.subscriptions.create
183
- @magazine.subscriptions.class.should == Array
184
- end
185
-
186
- it 'loads association one time only' do
187
- @sponsor = @magazine.sponsor.create
188
- @magazine.sponsor.expects(:find_target).once.returns(@sponsor)
189
-
190
- @magazine.sponsor.id
191
- @magazine.sponsor.id
192
- end
193
-
194
- end
@@ -1,71 +0,0 @@
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
- @camel_case = CamelCase.create
9
- end
10
-
11
- it 'determines nil if it has no associated record' do
12
- @subscription.magazine.should be_nil
13
- end
14
-
15
- it 'determines target association correctly' do
16
- @camel_case.magazine.send(:target_association).should == :camel_cases
17
- end
18
-
19
-
20
- it 'delegates equality to its source record' do
21
- @magazine = @subscription.magazine.create
22
-
23
- @subscription.magazine.should == @magazine
24
- end
25
-
26
- it 'associates has_many automatically' do
27
- @magazine = @subscription.magazine.create
28
-
29
- @magazine.subscriptions.should include @subscription
30
-
31
- @magazine = Magazine.create
32
- @user = @magazine.owner.create
33
- @user.books.size.should == 1
34
- @user.books.should include @magazine
35
- end
36
-
37
- it 'behaves like the object it is trying to be' do
38
- @magazine = @subscription.magazine.create
39
-
40
- @subscription.magazine.update_attribute(:title, 'Test Title')
41
-
42
- Magazine.first.title.should == 'Test Title'
43
- end
44
- end
45
-
46
- context 'has one' do
47
- before do
48
- @sponsor = Sponsor.create
49
- @subscription = Subscription.create
50
- end
51
-
52
- it 'determins nil if it has no associated record' do
53
- @sponsor.magazine.should be_nil
54
- end
55
-
56
- it 'delegates equality to its source record' do
57
- @magazine = @sponsor.magazine.create
58
-
59
- @sponsor.magazine.should == @magazine
60
- end
61
-
62
- it 'associates has_one automatically' do
63
- @magazine = @sponsor.magazine.create
64
-
65
- @magazine.sponsor.should == @sponsor
66
-
67
- @user = @subscription.customer.create
68
- @user.monthly.should == @subscription
69
- end
70
- end
71
- end
@@ -1,47 +0,0 @@
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
- @camel_case = CamelCase.create
8
- end
9
-
10
- it 'determines equality from its records' do
11
- @user = @subscription.users.create
12
-
13
- @subscription.users.size.should == 1
14
- @subscription.users.should include @user
15
- end
16
-
17
- it 'determines target association correctly' do
18
- @subscription.users.send(:target_association).should == :subscriptions
19
- @camel_case.subscriptions.send(:target_association).should == :camel_cases
20
- end
21
-
22
- it 'determines target attribute' do
23
- @subscription.users.send(:target_attribute).should == :subscriptions_ids
24
- end
25
-
26
- it 'associates has_and_belongs_to_many automatically' do
27
- @user = @subscription.users.create
28
-
29
- @user.subscriptions.size.should == 1
30
- @user.subscriptions.should include @subscription
31
- @subscription.users.size.should == 1
32
- @subscription.users.should include @user
33
-
34
- @user = User.create
35
- @follower = @user.followers.create
36
- @follower.following.should include @user
37
- @user.followers.should include @follower
38
- end
39
-
40
- it 'disassociates has_and_belongs_to_many automatically' do
41
- @user = @subscription.users.create
42
-
43
- @subscription.users.delete(@user)
44
- @subscription.users.size.should == 0
45
- @user.subscriptions.size.should == 0
46
- end
47
- end