massive_record 0.2.1 → 0.2.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +58 -2
- data/Gemfile.lock +17 -17
- data/README.md +98 -41
- data/lib/massive_record.rb +2 -1
- data/lib/massive_record/adapters/thrift/hbase/hbase.rb +2425 -2154
- data/lib/massive_record/adapters/thrift/hbase/hbase_constants.rb +3 -3
- data/lib/massive_record/adapters/thrift/hbase/hbase_types.rb +195 -195
- data/lib/massive_record/adapters/thrift/row.rb +35 -4
- data/lib/massive_record/adapters/thrift/table.rb +49 -12
- data/lib/massive_record/orm/attribute_methods.rb +77 -5
- data/lib/massive_record/orm/attribute_methods/cast_numbers_on_write.rb +24 -0
- data/lib/massive_record/orm/attribute_methods/dirty.rb +18 -0
- data/lib/massive_record/orm/attribute_methods/time_zone_conversion.rb +24 -3
- data/lib/massive_record/orm/attribute_methods/write.rb +8 -1
- data/lib/massive_record/orm/base.rb +62 -8
- data/lib/massive_record/orm/column.rb +7 -11
- data/lib/massive_record/orm/default_id.rb +1 -1
- data/lib/massive_record/orm/embedded.rb +66 -0
- data/lib/massive_record/orm/errors.rb +17 -0
- data/lib/massive_record/orm/finders.rb +124 -71
- data/lib/massive_record/orm/finders/rescue_missing_table_on_find.rb +1 -1
- data/lib/massive_record/orm/finders/scope.rb +58 -34
- data/lib/massive_record/orm/id_factory.rb +22 -105
- data/lib/massive_record/orm/id_factory/atomic_incrementation.rb +117 -0
- data/lib/massive_record/orm/id_factory/timestamp.rb +60 -0
- data/lib/massive_record/orm/identity_map.rb +256 -0
- data/lib/massive_record/orm/log_subscriber.rb +18 -0
- data/lib/massive_record/orm/observer.rb +69 -0
- data/lib/massive_record/orm/persistence.rb +47 -119
- data/lib/massive_record/orm/persistence/operations.rb +100 -0
- data/lib/massive_record/orm/persistence/operations/atomic_operation.rb +71 -0
- data/lib/massive_record/orm/persistence/operations/destroy.rb +17 -0
- data/lib/massive_record/orm/persistence/operations/embedded/destroy.rb +26 -0
- data/lib/massive_record/orm/persistence/operations/embedded/insert.rb +27 -0
- data/lib/massive_record/orm/persistence/operations/embedded/operation_helpers.rb +66 -0
- data/lib/massive_record/orm/persistence/operations/embedded/reload.rb +39 -0
- data/lib/massive_record/orm/persistence/operations/embedded/update.rb +29 -0
- data/lib/massive_record/orm/persistence/operations/insert.rb +19 -0
- data/lib/massive_record/orm/persistence/operations/reload.rb +26 -0
- data/lib/massive_record/orm/persistence/operations/suppress.rb +15 -0
- data/lib/massive_record/orm/persistence/operations/table_operation_helpers.rb +106 -0
- data/lib/massive_record/orm/persistence/operations/update.rb +25 -0
- data/lib/massive_record/orm/query_instrumentation.rb +26 -49
- data/lib/massive_record/orm/raw_data.rb +47 -0
- data/lib/massive_record/orm/relations.rb +4 -0
- data/lib/massive_record/orm/relations/interface.rb +134 -0
- data/lib/massive_record/orm/relations/metadata.rb +58 -12
- data/lib/massive_record/orm/relations/proxy.rb +17 -12
- data/lib/massive_record/orm/relations/proxy/embedded_in.rb +54 -0
- data/lib/massive_record/orm/relations/proxy/embedded_in_polymorphic.rb +15 -0
- data/lib/massive_record/orm/relations/proxy/embeds_many.rb +215 -0
- data/lib/massive_record/orm/relations/proxy/references_many.rb +112 -88
- data/lib/massive_record/orm/relations/proxy/references_one.rb +1 -1
- data/lib/massive_record/orm/relations/proxy/references_one_polymorphic.rb +1 -1
- data/lib/massive_record/orm/relations/proxy_collection.rb +84 -0
- data/lib/massive_record/orm/schema/column_family.rb +3 -2
- data/lib/massive_record/orm/schema/{column_interface.rb → embedded_interface.rb} +38 -4
- data/lib/massive_record/orm/schema/field.rb +2 -0
- data/lib/massive_record/orm/schema/table_interface.rb +19 -2
- data/lib/massive_record/orm/single_table_inheritance.rb +37 -2
- data/lib/massive_record/orm/timestamps.rb +17 -7
- data/lib/massive_record/orm/validations.rb +4 -0
- data/lib/massive_record/orm/validations/associated.rb +50 -0
- data/lib/massive_record/rails/railtie.rb +31 -0
- data/lib/massive_record/version.rb +1 -1
- data/lib/massive_record/wrapper/cell.rb +8 -1
- data/massive_record.gemspec +4 -4
- data/spec/adapter/thrift/atomic_increment_spec.rb +16 -0
- data/spec/adapter/thrift/table_find_spec.rb +14 -2
- data/spec/adapter/thrift/table_spec.rb +6 -6
- data/spec/adapter/thrift/utf8_encoding_of_id_spec.rb +71 -0
- data/spec/orm/cases/attribute_methods_spec.rb +215 -22
- data/spec/orm/cases/auto_generate_id_spec.rb +1 -1
- data/spec/orm/cases/change_id_spec.rb +62 -0
- data/spec/orm/cases/default_id_spec.rb +25 -6
- data/spec/orm/cases/default_values_spec.rb +6 -3
- data/spec/orm/cases/dirty_spec.rb +150 -102
- data/spec/orm/cases/embedded_spec.rb +250 -0
- data/spec/orm/cases/{finder_default_scope.rb → finder_default_scope_spec.rb} +4 -0
- data/spec/orm/cases/finder_scope_spec.rb +96 -29
- data/spec/orm/cases/finders_spec.rb +57 -10
- data/spec/orm/cases/id_factory/atomic_incrementation_spec.rb +72 -0
- data/spec/orm/cases/id_factory/timestamp_spec.rb +61 -0
- data/spec/orm/cases/identity_map/identity_map_spec.rb +357 -0
- data/spec/orm/cases/identity_map/middleware_spec.rb +74 -0
- data/spec/orm/cases/log_subscriber_spec.rb +15 -2
- data/spec/orm/cases/observing_spec.rb +61 -0
- data/spec/orm/cases/persistence_spec.rb +151 -60
- data/spec/orm/cases/raw_data_spec.rb +58 -0
- data/spec/orm/cases/single_table_inheritance_spec.rb +58 -2
- data/spec/orm/cases/table_spec.rb +3 -3
- data/spec/orm/cases/time_zone_awareness_spec.rb +27 -0
- data/spec/orm/cases/timestamps_spec.rb +23 -109
- data/spec/orm/cases/validation_spec.rb +9 -0
- data/spec/orm/models/address.rb +5 -1
- data/spec/orm/models/address_with_timestamp.rb +12 -0
- data/spec/orm/models/car.rb +5 -0
- data/spec/orm/models/person.rb +13 -1
- data/spec/orm/models/person_with_timestamp.rb +4 -2
- data/spec/orm/models/test_class.rb +1 -0
- data/spec/orm/persistence/operations/atomic_operation_spec.rb +58 -0
- data/spec/orm/persistence/operations/destroy_spec.rb +22 -0
- data/spec/orm/persistence/operations/embedded/destroy_spec.rb +71 -0
- data/spec/orm/persistence/operations/embedded/insert_spec.rb +59 -0
- data/spec/orm/persistence/operations/embedded/operation_helpers_spec.rb +92 -0
- data/spec/orm/persistence/operations/embedded/reload_spec.rb +67 -0
- data/spec/orm/persistence/operations/embedded/update_spec.rb +60 -0
- data/spec/orm/persistence/operations/insert_spec.rb +31 -0
- data/spec/orm/persistence/operations/reload_spec.rb +48 -0
- data/spec/orm/persistence/operations/suppress_spec.rb +17 -0
- data/spec/orm/persistence/operations/table_operation_helpers_spec.rb +98 -0
- data/spec/orm/persistence/operations/update_spec.rb +25 -0
- data/spec/orm/persistence/operations_spec.rb +58 -0
- data/spec/orm/relations/interface_spec.rb +188 -0
- data/spec/orm/relations/metadata_spec.rb +92 -15
- data/spec/orm/relations/proxy/embedded_in_polymorphic_spec.rb +37 -0
- data/spec/orm/relations/proxy/embedded_in_spec.rb +66 -0
- data/spec/orm/relations/proxy/embeds_many_spec.rb +651 -0
- data/spec/orm/relations/proxy/references_many_spec.rb +466 -2
- data/spec/orm/schema/column_family_spec.rb +21 -0
- data/spec/orm/schema/embedded_interface_spec.rb +181 -0
- data/spec/orm/schema/field_spec.rb +7 -0
- data/spec/orm/schema/table_interface_spec.rb +31 -1
- data/spec/shared/orm/id_factories.rb +44 -0
- data/spec/shared/orm/model_with_timestamps.rb +132 -0
- data/spec/shared/orm/persistence/a_persistence_embedded_operation_class.rb +3 -0
- data/spec/shared/orm/persistence/a_persistence_operation_class.rb +11 -0
- data/spec/shared/orm/persistence/a_persistence_table_operation_class.rb +11 -0
- data/spec/shared/orm/relations/proxy.rb +9 -2
- data/spec/spec_helper.rb +9 -0
- data/spec/support/mock_massive_record_connection.rb +2 -1
- metadata +106 -21
- data/spec/orm/cases/column_spec.rb +0 -49
- data/spec/orm/cases/id_factory_spec.rb +0 -92
- data/spec/orm/schema/column_interface_spec.rb +0 -136
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'orm/models/address'
|
3
|
+
|
4
|
+
describe MassiveRecord::ORM::Embedded do
|
5
|
+
subject { Address.new(:street => "Asker", :number => 5) }
|
6
|
+
let(:person) { Person.new "person-id", :name => "Thorbjorn", :age => "22" }
|
7
|
+
|
8
|
+
it "should have known_attribute_names" do
|
9
|
+
Address.should have(4).known_attribute_names
|
10
|
+
Address.known_attribute_names.should include("street", "number", "nice_place")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have default_attributes_from_schema" do
|
14
|
+
Address.default_attributes_from_schema["street"].should be_nil
|
15
|
+
Address.default_attributes_from_schema["number"].should be_nil
|
16
|
+
Address.default_attributes_from_schema["nice_place"].should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have attributes_schema" do
|
20
|
+
Address.attributes_schema["street"].should be_instance_of MassiveRecord::ORM::Schema::Field
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have a default value set" do
|
24
|
+
subject.nice_place.should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# TODO We might want to remove this when we have implemented
|
29
|
+
# associations correctly. Since Columns are contained within
|
30
|
+
# tables, calling save should do something on it's proxy_owner object.
|
31
|
+
describe "not be possible to persist (at least for now...)" do
|
32
|
+
%w(first last all exists? destroy_all).each do |method|
|
33
|
+
it "should not respond to class method #{method}" do
|
34
|
+
Address.should_not respond_to method
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
%w(
|
39
|
+
reload save save! save
|
40
|
+
update_attribute update_attributes update_attributes! touch destroy
|
41
|
+
delete increment! decrement! atomic_increment! atomic_decrement!
|
42
|
+
).each do |method|
|
43
|
+
it "do respond to #{method}" do
|
44
|
+
subject.should respond_to method
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
describe "persistence" do
|
51
|
+
include SetUpHbaseConnectionBeforeAll
|
52
|
+
include SetTableNamesToTestTable
|
53
|
+
|
54
|
+
describe "#save" do
|
55
|
+
context "not embedded" do
|
56
|
+
before { subject.person = nil }
|
57
|
+
|
58
|
+
it "raises error" do
|
59
|
+
expect { subject.save }.to raise_error MassiveRecord::ORM::NotAssignedToEmbeddedCollection
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "embedded in a collection" do
|
64
|
+
context "collection owner not persisted" do
|
65
|
+
before { subject.person = person }
|
66
|
+
|
67
|
+
it "gets assigned an id" do
|
68
|
+
subject.save
|
69
|
+
subject.id.should_not be_blank
|
70
|
+
end
|
71
|
+
|
72
|
+
it "saves both embedded record and embedded in record" do
|
73
|
+
subject.save
|
74
|
+
|
75
|
+
person.should be_persisted
|
76
|
+
subject.should be_persisted
|
77
|
+
end
|
78
|
+
|
79
|
+
it "does nothing if validations fail on embedded" do
|
80
|
+
subject.street = nil
|
81
|
+
subject.save
|
82
|
+
subject.errors.should_not be_empty
|
83
|
+
|
84
|
+
person.should_not be_persisted
|
85
|
+
subject.should_not be_persisted
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "validations fails on owner" do
|
89
|
+
before { person.name = nil }
|
90
|
+
|
91
|
+
it "does not persist owner" do
|
92
|
+
subject.save
|
93
|
+
person.should_not be_persisted
|
94
|
+
end
|
95
|
+
|
96
|
+
it "does not mark embedded as persisted" do
|
97
|
+
subject.save
|
98
|
+
subject.should_not be_persisted
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "colletion owner persisted" do
|
104
|
+
before do
|
105
|
+
person.save!
|
106
|
+
subject.person = person
|
107
|
+
end
|
108
|
+
|
109
|
+
it "gets assigned an id" do
|
110
|
+
subject.id.should_not be_blank
|
111
|
+
end
|
112
|
+
|
113
|
+
it "persists address" do
|
114
|
+
subject.street = "new_address"
|
115
|
+
subject.save
|
116
|
+
person.reload.addresses.first.street.should eq "new_address"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "will not save changes in owner when embedded is saved" do
|
120
|
+
subject.street += "_NEW"
|
121
|
+
person.name += "_NEW"
|
122
|
+
|
123
|
+
subject.save
|
124
|
+
|
125
|
+
person.should be_name_changed
|
126
|
+
end
|
127
|
+
|
128
|
+
it "does nothing if validations fail on embedded" do
|
129
|
+
subject.street = nil
|
130
|
+
subject.save
|
131
|
+
subject.errors.should_not be_empty
|
132
|
+
|
133
|
+
subject.should be_changed
|
134
|
+
end
|
135
|
+
|
136
|
+
it "save even if validations fails on owner of collection embedded in" do
|
137
|
+
person.name = nil
|
138
|
+
subject.street += "_NEW"
|
139
|
+
subject.save
|
140
|
+
|
141
|
+
subject.should_not be_changed
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
describe "#destroy" do
|
149
|
+
context "not emedded" do
|
150
|
+
before { subject.person = nil }
|
151
|
+
|
152
|
+
it "marks itself as destroyed" do
|
153
|
+
subject.destroy
|
154
|
+
subject.should be_destroyed
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "embedded" do
|
159
|
+
context "collection owner new record" do
|
160
|
+
before { subject.person = person }
|
161
|
+
|
162
|
+
it "marks itself as destroyed" do
|
163
|
+
subject.destroy
|
164
|
+
subject.should be_destroyed
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "collection owner persisted" do
|
169
|
+
before do
|
170
|
+
subject.person = person
|
171
|
+
person.save!
|
172
|
+
end
|
173
|
+
|
174
|
+
it "marks itself as destroyed" do
|
175
|
+
subject.destroy
|
176
|
+
subject.should be_destroyed
|
177
|
+
end
|
178
|
+
|
179
|
+
it "is removed from embeds_many collection" do
|
180
|
+
subject.destroy
|
181
|
+
person.addresses.should be_empty
|
182
|
+
end
|
183
|
+
|
184
|
+
it "is actually removed from collection" do
|
185
|
+
subject.destroy
|
186
|
+
person.reload.addresses.should be_empty
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "id" do
|
194
|
+
include SetUpHbaseConnectionBeforeAll
|
195
|
+
include SetTableNamesToTestTable
|
196
|
+
|
197
|
+
describe "assignment on first save" do
|
198
|
+
it "has no id when first instantiated" do
|
199
|
+
subject.id.should be_nil
|
200
|
+
end
|
201
|
+
|
202
|
+
it "gets an id on explicit save" do
|
203
|
+
subject.person = person
|
204
|
+
subject.save
|
205
|
+
subject.id.should_not be_nil
|
206
|
+
end
|
207
|
+
|
208
|
+
it "gets an id when saved through persisted parent" do
|
209
|
+
person.save
|
210
|
+
person.addresses << subject
|
211
|
+
subject.id.should_not be_nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "#database_id" do
|
216
|
+
let(:base_class) { Address.base_class.to_s.underscore }
|
217
|
+
|
218
|
+
describe "reader" do
|
219
|
+
it "has non when first instantiated" do
|
220
|
+
subject.database_id.should be_nil
|
221
|
+
end
|
222
|
+
|
223
|
+
it "gets one on explicit save" do
|
224
|
+
subject.person = person
|
225
|
+
subject.save
|
226
|
+
subject.database_id.should eq [base_class, subject.id].join(MassiveRecord::ORM::Embedded::DATABASE_ID_SEPARATOR)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "gets one when saved through persisted parent" do
|
230
|
+
person.save
|
231
|
+
person.addresses << subject
|
232
|
+
subject.database_id.should eq [base_class, subject.id].join(MassiveRecord::ORM::Embedded::DATABASE_ID_SEPARATOR)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "writer" do
|
237
|
+
it "splits base_class and id and assigns id to id" do
|
238
|
+
subject.database_id = "address#{MassiveRecord::ORM::Embedded::DATABASE_ID_SEPARATOR}166"
|
239
|
+
subject.id.should eq "166"
|
240
|
+
end
|
241
|
+
|
242
|
+
it "raises an error if database id could not be parsed" do
|
243
|
+
expect {
|
244
|
+
subject.database_id = "address-166"
|
245
|
+
}.to raise_error MassiveRecord::ORM::InvalidEmbeddedDatabaseId
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -56,5 +56,9 @@ describe "Default scope in" do
|
|
56
56
|
Person.default_scoping.should be_instance_of MassiveRecord::ORM::Finders::Scope
|
57
57
|
TestClass.default_scoping.should be_nil
|
58
58
|
end
|
59
|
+
|
60
|
+
it "returns a new scope object when default_scope are set" do
|
61
|
+
Person.finder_scope.should_not eq Person.finder_scope
|
62
|
+
end
|
59
63
|
end
|
60
64
|
end
|
@@ -21,8 +21,8 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
21
21
|
(MassiveRecord::ORM::Finders::Scope::MULTI_VALUE_METHODS + MassiveRecord::ORM::Finders::Scope::SINGLE_VALUE_METHODS).each do |method|
|
22
22
|
it { should respond_to(method) }
|
23
23
|
|
24
|
-
it "should return self
|
25
|
-
subject.send(method, nil).should
|
24
|
+
it "should return an instance of self #{method}()" do
|
25
|
+
subject.send(method, nil).should be_instance_of described_class
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -31,33 +31,27 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
31
31
|
describe "multi value methods" do
|
32
32
|
describe "select" do
|
33
33
|
it "should not add nil values" do
|
34
|
-
subject.select(nil)
|
35
|
-
subject.select_values.should be_empty
|
34
|
+
subject.select(nil).select_values.should be_empty
|
36
35
|
end
|
37
36
|
|
38
37
|
it "should add incomming value to list" do
|
39
|
-
subject.select(:info)
|
40
|
-
subject.select_values.should include 'info'
|
38
|
+
subject.select(:info).select_values.should include 'info'
|
41
39
|
end
|
42
40
|
|
43
41
|
it "should be adding values if called twice" do
|
44
|
-
subject.select(:info).select(:base)
|
45
|
-
subject.select_values.should include 'info', 'base'
|
42
|
+
subject.select(:info).select(:base).select_values.should include 'info', 'base'
|
46
43
|
end
|
47
44
|
|
48
45
|
it "should add multiple arguments" do
|
49
|
-
subject.select(:info, :base)
|
50
|
-
subject.select_values.should include 'info', 'base'
|
46
|
+
subject.select(:info, :base).select_values.should include 'info', 'base'
|
51
47
|
end
|
52
48
|
|
53
49
|
it "should add multiple values given as array" do
|
54
|
-
subject.select([:info, :base])
|
55
|
-
subject.select_values.should include 'info', 'base'
|
50
|
+
subject.select([:info, :base]).select_values.should include 'info', 'base'
|
56
51
|
end
|
57
52
|
|
58
53
|
it "should not add same value twice" do
|
59
|
-
subject.select(:info).select('info')
|
60
|
-
subject.select_values.should == ['info']
|
54
|
+
subject.select(:info).select('info').select_values.should == ['info']
|
61
55
|
end
|
62
56
|
end
|
63
57
|
end
|
@@ -67,13 +61,31 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
67
61
|
describe "singel value methods" do
|
68
62
|
describe "limit" do
|
69
63
|
it "should set a limit" do
|
70
|
-
subject.limit(5)
|
71
|
-
subject.limit_value.should == 5
|
64
|
+
subject.limit(5).limit_value.should == 5
|
72
65
|
end
|
73
66
|
|
74
67
|
it "should be set to the last value set" do
|
75
|
-
subject.limit(1).limit(5)
|
76
|
-
|
68
|
+
subject.limit(1).limit(5).limit_value.should == 5
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "starts_with" do
|
73
|
+
it "should set a starts_with" do
|
74
|
+
subject.starts_with(5).starts_with_value.should == 5
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should be set to the last value set" do
|
78
|
+
subject.starts_with(1).starts_with(5).starts_with_value.should == 5
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "offset" do
|
83
|
+
it "should set a offset" do
|
84
|
+
subject.offset(5).offset_value.should == 5
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should be set to the last value set" do
|
88
|
+
subject.offset(1).offset(5).offset_value.should == 5
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end
|
@@ -92,6 +104,14 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
92
104
|
it "should include selection when asked for it" do
|
93
105
|
subject.select(:info).send(:find_options).should include :select => ['info']
|
94
106
|
end
|
107
|
+
|
108
|
+
it "includes a starts_with when asked for it" do
|
109
|
+
subject.starts_with("id-something").send(:find_options).should include :starts_with => "id-something"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "includes an offset when asked for it" do
|
113
|
+
subject.offset("id-something").send(:find_options).should include :offset => "id-something"
|
114
|
+
end
|
95
115
|
end
|
96
116
|
|
97
117
|
|
@@ -104,13 +124,31 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
104
124
|
end
|
105
125
|
end
|
106
126
|
|
107
|
-
|
108
127
|
describe "#reset" do
|
109
|
-
it "
|
128
|
+
it "resets the loaded status" do
|
110
129
|
subject.loaded = true
|
111
130
|
subject.reset
|
112
131
|
should_not be_loaded
|
113
132
|
end
|
133
|
+
|
134
|
+
it "resets the loaded records" do
|
135
|
+
records = [:foo]
|
136
|
+
subject.instance_variable_set(:@records, records)
|
137
|
+
subject.reset
|
138
|
+
subject.instance_variable_get(:@records).should be_empty
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "a clone" do
|
143
|
+
it "resets the state after being cloned" do
|
144
|
+
records = [:foo]
|
145
|
+
subject.instance_variable_set(:@records, records)
|
146
|
+
subject.loaded = true
|
147
|
+
|
148
|
+
cloned = subject.clone
|
149
|
+
cloned.should_not be_loaded
|
150
|
+
cloned.instance_variable_get(:@records).should be_empty
|
151
|
+
end
|
114
152
|
end
|
115
153
|
|
116
154
|
describe "#to_a" do
|
@@ -123,7 +161,7 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
123
161
|
end
|
124
162
|
|
125
163
|
|
126
|
-
[:to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?].each do |method|
|
164
|
+
[:to_xml, :to_yaml, :length, :size, :collect, :map, :each, :all?, :include?].each do |method|
|
127
165
|
it "should delegate #{method} to to_a" do
|
128
166
|
records = []
|
129
167
|
records.should_receive(method)
|
@@ -157,6 +195,15 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
157
195
|
subject.should_receive(:klass).and_return(klass)
|
158
196
|
subject.select(:foo).find(1)
|
159
197
|
end
|
198
|
+
|
199
|
+
it "should include finder options" do
|
200
|
+
extra_options = {:select => ["foo"], :conditions => 'should_be_passed_on_to_finder'}
|
201
|
+
klass = mock(Object)
|
202
|
+
klass.should_receive(:do_find).with("ID", hash_including(extra_options)).and_return([])
|
203
|
+
subject.instance_variable_set(:@klass, klass)
|
204
|
+
|
205
|
+
subject.find("ID", extra_options)
|
206
|
+
end
|
160
207
|
end
|
161
208
|
|
162
209
|
|
@@ -176,7 +223,7 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
176
223
|
|
177
224
|
klass = mock(Object)
|
178
225
|
klass.should_receive(:do_find).with(anything, hash_including(extra_options)).and_return([])
|
179
|
-
subject.
|
226
|
+
subject.instance_variable_set(:@klass, klass)
|
180
227
|
|
181
228
|
subject.first(extra_options)
|
182
229
|
end
|
@@ -194,7 +241,7 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
194
241
|
|
195
242
|
klass = mock(Object)
|
196
243
|
klass.should_receive(:do_find).with(anything, extra_options)
|
197
|
-
subject.
|
244
|
+
subject.instance_variable_set(:@klass, klass)
|
198
245
|
|
199
246
|
subject.all(extra_options)
|
200
247
|
end
|
@@ -219,10 +266,12 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
219
266
|
describe "with a person" do
|
220
267
|
let(:person_1) { Person.create "ID1", :name => "Person1", :email => "one@person.com", :age => 11, :points => 111, :status => true }
|
221
268
|
let(:person_2) { Person.create "ID2", :name => "Person2", :email => "two@person.com", :age => 22, :points => 222, :status => false }
|
269
|
+
let(:person_3) { Person.create "other", :name => "Person3", :email => "three@person.com", :age => 33, :points => 333, :status => true }
|
222
270
|
|
223
271
|
before do
|
224
272
|
person_1.save!
|
225
273
|
person_2.save!
|
274
|
+
person_3.save!
|
226
275
|
end
|
227
276
|
|
228
277
|
(MassiveRecord::ORM::Finders::Scope::MULTI_VALUE_METHODS + MassiveRecord::ORM::Finders::Scope::SINGLE_VALUE_METHODS).each do |method|
|
@@ -244,15 +293,33 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
244
293
|
person_from_db.status.should be_nil
|
245
294
|
end
|
246
295
|
|
296
|
+
it "applying scope on a loaded scope returns a cloned and reset scope" do
|
297
|
+
scope = Person.limit(2)
|
298
|
+
scope.all.should eq [person_1, person_2]
|
299
|
+
scope.should be_loaded
|
300
|
+
|
301
|
+
new_scope = scope.offset("ID2")
|
302
|
+
new_scope.should_not be_loaded
|
303
|
+
new_scope.all.should eq [person_2, person_3]
|
304
|
+
end
|
305
|
+
|
247
306
|
it "should not return read only objects when select is used" do
|
248
307
|
person = Person.select(:info).first
|
249
308
|
person.should_not be_readonly
|
250
309
|
end
|
251
310
|
|
311
|
+
it "ensures records starts with string" do
|
312
|
+
Person.starts_with("ID").should == [person_1, person_2]
|
313
|
+
end
|
314
|
+
|
315
|
+
it "sets an offset point to begin read rows from" do
|
316
|
+
Person.offset("ID2").should == [person_2, person_3]
|
317
|
+
end
|
318
|
+
|
252
319
|
it "should be possible to iterate over a collection with each" do
|
253
320
|
result = []
|
254
321
|
|
255
|
-
Person.limit(
|
322
|
+
Person.starts_with("ID").limit(2).each do |person|
|
256
323
|
result << person.name
|
257
324
|
end
|
258
325
|
|
@@ -260,7 +327,7 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
260
327
|
end
|
261
328
|
|
262
329
|
it "should be possible to collect" do
|
263
|
-
Person.select(:info).collect(&:name).should == ["Person1", "Person2"]
|
330
|
+
Person.select(:info).collect(&:name).should == ["Person1", "Person2", "Person3"]
|
264
331
|
end
|
265
332
|
|
266
333
|
it "should be possible to checkc if it includes something" do
|
@@ -272,13 +339,13 @@ describe MassiveRecord::ORM::Finders::Scope do
|
|
272
339
|
|
273
340
|
describe "#apply_finder_options" do
|
274
341
|
it "should apply limit correctly" do
|
275
|
-
subject.
|
276
|
-
|
342
|
+
scope = subject.send :apply_finder_options, :limit => 30
|
343
|
+
scope.limit_value.should eq 30
|
277
344
|
end
|
278
345
|
|
279
346
|
it "should apply select correctly" do
|
280
|
-
subject.
|
281
|
-
|
347
|
+
scope = subject.send :apply_finder_options, :select => :foo
|
348
|
+
scope.select_values.should include 'foo'
|
282
349
|
end
|
283
350
|
|
284
351
|
it "should raise unknown scope error if options is unkown" do
|