massive_record 0.2.1 → 0.2.2.rc1
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/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
|