massive_record 0.1.1 → 0.2.0.beta
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 +28 -5
- data/Gemfile.lock +12 -12
- data/README.md +29 -1
- data/lib/massive_record/adapters/initialize.rb +18 -0
- data/lib/massive_record/adapters/thrift/adapter.rb +25 -0
- data/lib/massive_record/adapters/thrift/column_family.rb +24 -0
- data/lib/massive_record/adapters/thrift/connection.rb +73 -0
- data/lib/massive_record/{thrift → adapters/thrift/hbase}/hbase.rb +0 -0
- data/lib/massive_record/{thrift → adapters/thrift/hbase}/hbase_constants.rb +0 -0
- data/lib/massive_record/{thrift → adapters/thrift/hbase}/hbase_types.rb +0 -0
- data/lib/massive_record/adapters/thrift/row.rb +150 -0
- data/lib/massive_record/adapters/thrift/scanner.rb +59 -0
- data/lib/massive_record/adapters/thrift/table.rb +169 -0
- data/lib/massive_record/orm/attribute_methods/read.rb +2 -1
- data/lib/massive_record/orm/base.rb +61 -3
- data/lib/massive_record/orm/coders/chained.rb +71 -0
- data/lib/massive_record/orm/coders/json.rb +17 -0
- data/lib/massive_record/orm/coders/yaml.rb +15 -0
- data/lib/massive_record/orm/coders.rb +3 -0
- data/lib/massive_record/orm/errors.rb +15 -2
- data/lib/massive_record/orm/finders/scope.rb +166 -0
- data/lib/massive_record/orm/finders.rb +45 -24
- data/lib/massive_record/orm/persistence.rb +4 -4
- data/lib/massive_record/orm/relations/interface.rb +170 -0
- data/lib/massive_record/orm/relations/metadata.rb +150 -0
- data/lib/massive_record/orm/relations/proxy/references_many.rb +229 -0
- data/lib/massive_record/orm/relations/proxy/references_one.rb +40 -0
- data/lib/massive_record/orm/relations/proxy/references_one_polymorphic.rb +49 -0
- data/lib/massive_record/orm/relations/proxy.rb +174 -0
- data/lib/massive_record/orm/relations.rb +6 -0
- data/lib/massive_record/orm/schema/column_interface.rb +1 -1
- data/lib/massive_record/orm/schema/field.rb +62 -27
- data/lib/massive_record/orm/single_table_inheritance.rb +21 -0
- data/lib/massive_record/version.rb +1 -1
- data/lib/massive_record/wrapper/adapter.rb +6 -0
- data/lib/massive_record/wrapper/base.rb +6 -7
- data/lib/massive_record/wrapper/cell.rb +9 -32
- data/lib/massive_record/wrapper/column_families_collection.rb +2 -2
- data/lib/massive_record/wrapper/errors.rb +10 -0
- data/lib/massive_record/wrapper/tables_collection.rb +1 -1
- data/lib/massive_record.rb +5 -12
- data/spec/orm/cases/attribute_methods_spec.rb +5 -1
- data/spec/orm/cases/base_spec.rb +77 -4
- data/spec/orm/cases/column_spec.rb +1 -1
- data/spec/orm/cases/finder_default_scope.rb +53 -0
- data/spec/orm/cases/finder_scope_spec.rb +288 -0
- data/spec/orm/cases/finders_spec.rb +56 -13
- data/spec/orm/cases/persistence_spec.rb +20 -5
- data/spec/orm/cases/single_table_inheritance_spec.rb +26 -0
- data/spec/orm/cases/table_spec.rb +1 -1
- data/spec/orm/cases/timestamps_spec.rb +16 -16
- data/spec/orm/coders/chained_spec.rb +73 -0
- data/spec/orm/coders/json_spec.rb +6 -0
- data/spec/orm/coders/yaml_spec.rb +6 -0
- data/spec/orm/models/best_friend.rb +7 -0
- data/spec/orm/models/friend.rb +4 -0
- data/spec/orm/models/person.rb +20 -6
- data/spec/orm/models/{person_with_timestamps.rb → person_with_timestamp.rb} +1 -1
- data/spec/orm/models/test_class.rb +3 -0
- data/spec/orm/relations/interface_spec.rb +207 -0
- data/spec/orm/relations/metadata_spec.rb +202 -0
- data/spec/orm/relations/proxy/references_many_spec.rb +624 -0
- data/spec/orm/relations/proxy/references_one_polymorphic_spec.rb +106 -0
- data/spec/orm/relations/proxy/references_one_spec.rb +111 -0
- data/spec/orm/relations/proxy_spec.rb +13 -0
- data/spec/orm/schema/field_spec.rb +101 -2
- data/spec/shared/orm/coders/an_orm_coder.rb +14 -0
- data/spec/shared/orm/relations/proxy.rb +154 -0
- data/spec/shared/orm/relations/singular_proxy.rb +68 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/thrift/cases/encoding_spec.rb +28 -7
- data/spec/wrapper/cases/adapter_spec.rb +9 -0
- data/spec/wrapper/cases/connection_spec.rb +13 -10
- data/spec/wrapper/cases/table_spec.rb +85 -85
- metadata +74 -22
- data/TODO.md +0 -8
- data/lib/massive_record/exceptions.rb +0 -11
- data/lib/massive_record/wrapper/column_family.rb +0 -22
- data/lib/massive_record/wrapper/connection.rb +0 -71
- data/lib/massive_record/wrapper/row.rb +0 -173
- data/lib/massive_record/wrapper/scanner.rb +0 -61
- data/lib/massive_record/wrapper/table.rb +0 -149
- data/spec/orm/cases/hbase/connection_spec.rb +0 -13
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'orm/models/person'
|
3
|
+
require 'orm/models/person_with_timestamp'
|
4
|
+
|
5
|
+
describe MassiveRecord::ORM::Relations::Interface do
|
6
|
+
include SetUpHbaseConnectionBeforeAll
|
7
|
+
include SetTableNamesToTestTable
|
8
|
+
|
9
|
+
describe "class methods" do
|
10
|
+
subject { Person }
|
11
|
+
|
12
|
+
describe "should include" do
|
13
|
+
%w(references_one).each do |relation|
|
14
|
+
it { should respond_to relation }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not share relations" do
|
19
|
+
Person.relations.should_not == PersonWithTimestamp.relations
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
describe "references one" do
|
25
|
+
describe "relation's meta data" do
|
26
|
+
subject { Person.relations.detect { |relation| relation.name == "boss" } }
|
27
|
+
|
28
|
+
it "should have the reference one meta data stored in relations" do
|
29
|
+
Person.relations.detect { |relation| relation.name == "boss" }.should_not be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have type set to references_one" do
|
33
|
+
subject.relation_type.should == "references_one"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an error if the same relaton is called for twice" do
|
37
|
+
lambda { Person.references_one :boss }.should raise_error MassiveRecord::ORM::RelationAlreadyDefined
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe "instance" do
|
43
|
+
subject { Person.new }
|
44
|
+
let(:boss) { PersonWithTimestamp.new }
|
45
|
+
let(:proxy) { subject.send(:relation_proxy, "boss") }
|
46
|
+
|
47
|
+
it { should respond_to :boss }
|
48
|
+
it { should respond_to :boss= }
|
49
|
+
it { should respond_to :boss_id }
|
50
|
+
it { should respond_to :boss_id= }
|
51
|
+
|
52
|
+
|
53
|
+
describe "record getter and setter" do
|
54
|
+
it "should return nil if foreign_key is nil" do
|
55
|
+
subject.boss.should be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return the proxy's proxy_target if boss is set" do
|
59
|
+
subject.boss = boss
|
60
|
+
subject.boss.should == boss
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be able to reset the proxy" do
|
64
|
+
proxy.should_receive(:load_proxy_target).and_return(true)
|
65
|
+
proxy.should_receive(:reset)
|
66
|
+
subject.boss.reset
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should be able to reload the proxy" do
|
70
|
+
proxy.should_receive(:load_proxy_target).and_return(true)
|
71
|
+
proxy.should_receive(:reload)
|
72
|
+
subject.boss.reload
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should set the foreign_key in proxy_owner when proxy_target is set" do
|
76
|
+
subject.boss = boss
|
77
|
+
subject.boss_id.should == boss.id
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should load proxy_target object when read method is called" do
|
81
|
+
PersonWithTimestamp.should_receive(:find).and_return(boss)
|
82
|
+
subject.boss_id = boss.id
|
83
|
+
subject.boss.should == boss
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not load proxy_target twice" do
|
87
|
+
PersonWithTimestamp.should_receive(:find).once.and_return(boss)
|
88
|
+
subject.boss_id = boss.id
|
89
|
+
2.times { subject.boss }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
describe "references one polymorphic" do
|
97
|
+
describe "relation's meta data" do
|
98
|
+
subject { TestClass.relations.detect { |relation| relation.name == "attachable" } }
|
99
|
+
|
100
|
+
it "should have the reference one polymorphic meta data stored in relations" do
|
101
|
+
TestClass.relations.detect { |relation| relation.name == "attachable" }.should_not be_nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have type set to correct type" do
|
105
|
+
subject.relation_type.should == "references_one_polymorphic"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should raise an error if the same relaton is called for twice" do
|
109
|
+
lambda { TestClass.references_one :attachable }.should raise_error MassiveRecord::ORM::RelationAlreadyDefined
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
describe "instance" do
|
115
|
+
subject { TestClass.new }
|
116
|
+
let(:attachable) { Person.new }
|
117
|
+
|
118
|
+
it { should respond_to :attachable }
|
119
|
+
it { should respond_to :attachable= }
|
120
|
+
it { should respond_to :attachable_id }
|
121
|
+
it { should respond_to :attachable_id= }
|
122
|
+
it { should respond_to :attachable_type }
|
123
|
+
it { should respond_to :attachable_type= }
|
124
|
+
|
125
|
+
|
126
|
+
describe "record getter and setter" do
|
127
|
+
it "should return nil if foreign_key is nil" do
|
128
|
+
subject.attachable.should be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should return the proxy's proxy_target if attachable is set" do
|
132
|
+
subject.attachable = attachable
|
133
|
+
subject.attachable.should == attachable
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should set the foreign_key in proxy_owner when proxy_target is set" do
|
137
|
+
subject.attachable = attachable
|
138
|
+
subject.attachable_id.should == attachable.id
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should set the type in proxy_owner when proxy_target is set" do
|
142
|
+
subject.attachable = attachable
|
143
|
+
subject.attachable_type.should == attachable.class.to_s.underscore
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
[Person, PersonWithTimestamp].each do |polymorphic_class|
|
149
|
+
describe "polymorphic association to class #{polymorphic_class}" do
|
150
|
+
let (:attachable) { polymorphic_class.new :id => "ID1" }
|
151
|
+
|
152
|
+
before do
|
153
|
+
subject.attachable_id = attachable.id
|
154
|
+
subject.attachable_type = polymorphic_class.to_s.underscore
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should load proxy_target object when read method is called" do
|
158
|
+
polymorphic_class.should_receive(:find).and_return(attachable)
|
159
|
+
subject.attachable.should == attachable
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should not load proxy_target twice" do
|
163
|
+
polymorphic_class.should_receive(:find).once.and_return(attachable)
|
164
|
+
2.times { subject.attachable }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
describe "references many" do
|
176
|
+
describe "relation's meta data" do
|
177
|
+
subject { Person.relations.detect { |relation| relation.name == "test_classes" } }
|
178
|
+
|
179
|
+
it "should have the reference one meta data stored in relations" do
|
180
|
+
Person.relations.detect { |relation| relation.name == "test_classes" }.should_not be_nil
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should have type set to references_many" do
|
184
|
+
subject.relation_type.should == "references_many"
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should raise an error if the same relaton is called for twice" do
|
188
|
+
lambda { Person.references_one :test_classes }.should raise_error MassiveRecord::ORM::RelationAlreadyDefined
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
describe "instance" do
|
194
|
+
subject { Person.new }
|
195
|
+
let(:test_class) { TestClass.new }
|
196
|
+
let(:proxy) { subject.send(:relation_proxy, "test_classes") }
|
197
|
+
|
198
|
+
it { should respond_to :test_classes }
|
199
|
+
it { should respond_to :test_class_ids }
|
200
|
+
it { should respond_to :test_class_ids= }
|
201
|
+
|
202
|
+
it "should have an array as foreign_key attribute" do
|
203
|
+
subject.test_class_ids.should be_instance_of Array
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'orm/models/person'
|
3
|
+
|
4
|
+
describe MassiveRecord::ORM::Relations::Metadata do
|
5
|
+
subject { MassiveRecord::ORM::Relations::Metadata.new(nil) }
|
6
|
+
|
7
|
+
%w(name foreign_key class_name relation_type find_with polymorphic records_starts_from).each do |attr|
|
8
|
+
it { should respond_to attr }
|
9
|
+
it { should respond_to attr+"=" }
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
it "should be setting values by initializer" do
|
14
|
+
metadata = subject.class.new :car, :foreign_key => :my_car_id, :class_name => "Vehicle", :store_in => :info, :polymorphic => true, :records_starts_from => :records_starts_from
|
15
|
+
metadata.name.should == "car"
|
16
|
+
metadata.foreign_key.should == "my_car_id"
|
17
|
+
metadata.class_name.should == "Vehicle"
|
18
|
+
metadata.store_in.should == "info"
|
19
|
+
metadata.records_starts_from.should == :records_starts_from
|
20
|
+
metadata.should be_polymorphic
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be possible to set relation type through initializer" do
|
24
|
+
metadata = subject.class.new :car, :relation_type => :foo
|
25
|
+
metadata.relation_type.should be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
its(:name) { should be_nil }
|
30
|
+
|
31
|
+
it "should return name as string" do
|
32
|
+
subject.name = :foo
|
33
|
+
subject.name.should == "foo"
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe "#class_name" do
|
38
|
+
it "should return whatever it's being set to" do
|
39
|
+
subject.class_name = "Person"
|
40
|
+
subject.class_name.should == "Person"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return class name as a string" do
|
44
|
+
subject.class_name = Person
|
45
|
+
subject.class_name.should == "Person"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should calculate it from name" do
|
49
|
+
subject.name = :employee
|
50
|
+
subject.class_name.should == "Employee"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should calculate correct class name if represents a collection" do
|
54
|
+
subject.relation_type = "references_many"
|
55
|
+
subject.name = "persons"
|
56
|
+
subject.class_name.should == "Person"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
describe "#foreign_key" do
|
64
|
+
it "should return whatever it's being set to" do
|
65
|
+
subject.foreign_key = "person_id"
|
66
|
+
subject.foreign_key.should == "person_id"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return foreign key as string" do
|
70
|
+
subject.foreign_key = :person_id
|
71
|
+
subject.foreign_key.should == "person_id"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should try and calculate the foreign key from the name" do
|
75
|
+
subject.class_name = "PersonWithSomething"
|
76
|
+
subject.name = :person
|
77
|
+
subject.foreign_key.should == "person_id"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return plural for if meta data is representing a many relation" do
|
81
|
+
subject.relation_type = :references_many
|
82
|
+
subject.name = :persons
|
83
|
+
subject.foreign_key.should == "person_ids"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#foreign_key_setter" do
|
88
|
+
it "should return whatever the foreign_key is pluss =" do
|
89
|
+
subject.should_receive(:foreign_key).and_return("custom_key")
|
90
|
+
subject.foreign_key_setter.should == "custom_key="
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
describe "#store_in" do
|
97
|
+
its(:store_in) { should be_nil }
|
98
|
+
|
99
|
+
it "should be able to set column family to store foreign key in" do
|
100
|
+
subject.store_in = :info
|
101
|
+
subject.store_in.should == "info"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should know its persisting foreign key if foreign key stored in has been set" do
|
106
|
+
subject.store_in = :info
|
107
|
+
should be_persisting_foreign_key
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should not be storing the foreign key if records_starts_from is defined" do
|
111
|
+
subject.store_in = :info
|
112
|
+
subject.records_starts_from = :method_which_returns_a_starting_point
|
113
|
+
should_not be_persisting_foreign_key
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
it "should compare two meta datas based on name" do
|
119
|
+
other = MassiveRecord::ORM::Relations::Metadata.new(subject.name)
|
120
|
+
other.should == subject
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should have the same hash value for the same name" do
|
124
|
+
subject.hash == subject.name.hash
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
describe "#new_relation_proxy" do
|
130
|
+
let(:proxy_owner) { Person.new }
|
131
|
+
let(:proxy) { subject.relation_type = "references_one" and subject.new_relation_proxy(proxy_owner) }
|
132
|
+
|
133
|
+
it "should return a proxy where proxy_owner is assigned" do
|
134
|
+
proxy.proxy_owner.should == proxy_owner
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should return a proxy where metadata is assigned" do
|
138
|
+
proxy.metadata.should == subject
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should append _polymorphic to the proxy name if it is polymorphic" do
|
142
|
+
subject.polymorphic = true
|
143
|
+
subject.relation_type = "references_one"
|
144
|
+
subject.relation_type.should == "references_one_polymorphic"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
describe "#polymorphic_type_column" do
|
150
|
+
before do
|
151
|
+
subject.polymorphic = true
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should remove _id and add _type to foreign_key" do
|
155
|
+
subject.should_receive(:foreign_key).and_return("foo_id")
|
156
|
+
subject.polymorphic_type_column.should == "foo_type"
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should simply add _type if foreign_key does not end on _id" do
|
160
|
+
subject.should_receive(:foreign_key).and_return("foo_id_b")
|
161
|
+
subject.polymorphic_type_column.should == "foo_id_b_type"
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return setter method" do
|
165
|
+
subject.should_receive(:polymorphic_type_column).and_return("yey")
|
166
|
+
subject.polymorphic_type_column_setter.should == "yey="
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
describe "records_starts_from" do
|
172
|
+
it "should not have any proc if records_starts_from is nil" do
|
173
|
+
subject.find_with = "foo"
|
174
|
+
subject.records_starts_from = nil
|
175
|
+
subject.find_with.should be_nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should buld a proc with records_starts_from set" do
|
179
|
+
subject.records_starts_from = :friends_records_starts_from_id
|
180
|
+
subject.find_with.should be_instance_of Proc
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "proc" do
|
184
|
+
let(:proxy_owner) { Person.new :id => "person-1" }
|
185
|
+
let(:find_with_proc) { subject.records_starts_from = :friends_records_starts_from_id; subject.find_with }
|
186
|
+
|
187
|
+
before do
|
188
|
+
subject.class_name = "Person"
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should call proxy_target class with all, start with proxy_owner's start from id response" do
|
192
|
+
Person.should_receive(:all).with(hash_including(:start => proxy_owner.friends_records_starts_from_id))
|
193
|
+
find_with_proc.call(proxy_owner)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should be possible to send in options to the proc" do
|
197
|
+
Person.should_receive(:all).with(hash_including(:limit => 10, :start => proxy_owner.friends_records_starts_from_id))
|
198
|
+
find_with_proc.call(proxy_owner, {:limit => 10})
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,624 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestReferencesManyProxy < MassiveRecord::ORM::Relations::Proxy::ReferencesMany; end
|
4
|
+
|
5
|
+
describe TestReferencesManyProxy do
|
6
|
+
include SetUpHbaseConnectionBeforeAll
|
7
|
+
include SetTableNamesToTestTable
|
8
|
+
|
9
|
+
let(:proxy_owner) { Person.new :id => "person-id-1", :name => "Test", :age => 29 }
|
10
|
+
let(:proxy_target) { TestClass.new :id => "test-class-id-1" }
|
11
|
+
let(:proxy_target_2) { TestClass.new :id => "test-class-id-2" }
|
12
|
+
let(:proxy_target_3) { TestClass.new :id => "test-class-id-3" }
|
13
|
+
let(:metadata) { subject.metadata }
|
14
|
+
|
15
|
+
subject { proxy_owner.send(:relation_proxy, 'test_classes') }
|
16
|
+
|
17
|
+
it_should_behave_like "relation proxy"
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
describe "#find_proxy_target" do
|
22
|
+
describe "with foreig keys stored in proxy_owner" do
|
23
|
+
it "should not try to find proxy_target if foreign_keys is blank" do
|
24
|
+
proxy_owner.test_class_ids.clear
|
25
|
+
TestClass.should_not_receive(:find)
|
26
|
+
subject.load_proxy_target.should be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should try to load proxy_target if foreign_keys has any keys" do
|
30
|
+
proxy_owner.test_class_ids << proxy_target.id
|
31
|
+
TestClass.should_receive(:find).with([proxy_target.id], anything).and_return([proxy_target])
|
32
|
+
subject.load_proxy_target.should == [proxy_target]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not die when loading foreign keys which does not exist in proxy_target table" do
|
36
|
+
proxy_owner.save!
|
37
|
+
proxy_owner.test_classes << proxy_target
|
38
|
+
proxy_owner.test_classes.reset
|
39
|
+
proxy_owner.test_class_ids << "does_not_exists"
|
40
|
+
proxy_owner.test_classes.reload
|
41
|
+
proxy_owner.test_classes.length.should == 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "with start from" do
|
46
|
+
let(:proxy_target) { Person.new :id => proxy_owner.id+"-friend-1", :name => "T", :age => 2 }
|
47
|
+
let(:proxy_target_2) { Person.new :id => proxy_owner.id+"-friend-2", :name => "H", :age => 9 }
|
48
|
+
let(:not_proxy_target) { Person.new :id => "foo"+"-friend-2", :name => "H", :age => 1 }
|
49
|
+
let(:metadata) { subject.metadata }
|
50
|
+
|
51
|
+
subject { proxy_owner.send(:relation_proxy, 'friends') }
|
52
|
+
|
53
|
+
before do
|
54
|
+
proxy_target.save!
|
55
|
+
proxy_target_2.save!
|
56
|
+
not_proxy_target.save!
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not try to find proxy_target if start from method is blank" do
|
60
|
+
proxy_owner.should_receive(:friends_records_starts_from_id).and_return(nil)
|
61
|
+
Person.should_not_receive(:all)
|
62
|
+
subject.load_proxy_target.should be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should find all friends when loading" do
|
66
|
+
friends = subject.load_proxy_target
|
67
|
+
friends.length.should == 2
|
68
|
+
friends.should include(proxy_target)
|
69
|
+
friends.should include(proxy_target_2)
|
70
|
+
friends.should_not include(not_proxy_target)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "find with proc" do
|
76
|
+
let(:test_class) { TestClass.new }
|
77
|
+
|
78
|
+
before do
|
79
|
+
subject.metadata.find_with = Proc.new { |proxy_target| TestClass.find("testing-123") }
|
80
|
+
end
|
81
|
+
|
82
|
+
after do
|
83
|
+
subject.metadata.find_with = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not call find_proxy_target" do
|
87
|
+
should_not_receive :find_proxy_target
|
88
|
+
subject.load_proxy_target
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should load by given proc" do
|
92
|
+
TestClass.should_receive(:find).with("testing-123").and_return([test_class])
|
93
|
+
subject.load_proxy_target.should == [test_class]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should always wrap the proc's result in an array" do
|
97
|
+
TestClass.should_receive(:find).with("testing-123").and_return(test_class)
|
98
|
+
subject.load_proxy_target.should == [test_class]
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be empty if the proc return nil" do
|
102
|
+
TestClass.should_receive(:find).with("testing-123").and_return(nil)
|
103
|
+
subject.load_proxy_target.should be_empty
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
describe "adding records to collection" do
|
109
|
+
[:<<, :push, :concat].each do |add_method|
|
110
|
+
describe "by ##{add_method}" do
|
111
|
+
it "should include the proxy_target in the proxy" do
|
112
|
+
subject.send(add_method, proxy_target)
|
113
|
+
subject.proxy_target.should include proxy_target
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should not add invalid objects to collection" do
|
117
|
+
proxy_target.should_receive(:valid?).and_return false
|
118
|
+
subject.send(add_method, proxy_target).should be_false
|
119
|
+
subject.proxy_target.should_not include proxy_target
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should update array of foreign keys in proxy_owner" do
|
123
|
+
proxy_owner.test_class_ids.should be_empty
|
124
|
+
subject.send(add_method, proxy_target)
|
125
|
+
proxy_owner.test_class_ids.should include(proxy_target.id)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should auto-persist foreign keys if owner has been persisted" do
|
129
|
+
proxy_owner.save!
|
130
|
+
subject.send(add_method, proxy_target)
|
131
|
+
proxy_owner.reload
|
132
|
+
proxy_owner.test_class_ids.should include(proxy_target.id)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should not persist proxy owner (and it's foreign keys) if owner is a new record" do
|
136
|
+
subject.send(add_method, proxy_target)
|
137
|
+
proxy_owner.should be_new_record
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should not update array of foreign keys in proxy_owner if it does not respond to it" do
|
141
|
+
proxy_owner.should_receive(:respond_to?).twice.and_return(false)
|
142
|
+
subject.send(add_method, proxy_target)
|
143
|
+
proxy_owner.test_class_ids.should_not include(proxy_target.id)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not update array of foreign keys in the proxy owner if it has been destroyed" do
|
147
|
+
proxy_owner.should_receive(:destroyed?).and_return true
|
148
|
+
subject.send(add_method, proxy_target)
|
149
|
+
proxy_owner.test_class_ids.should_not include(proxy_target.id)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not do anything adding the same record twice" do
|
153
|
+
2.times { subject.send(add_method, proxy_target) }
|
154
|
+
subject.proxy_target.length.should == 1
|
155
|
+
proxy_owner.test_class_ids.length.should == 1
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should be able to add two records at the same time" do
|
159
|
+
subject.send add_method, [proxy_target, proxy_target_2]
|
160
|
+
subject.proxy_target.should include proxy_target
|
161
|
+
subject.proxy_target.should include proxy_target_2
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return proxy so calls can be chained" do
|
165
|
+
subject.send(add_method, proxy_target).object_id.should == subject.object_id
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should raise an error if there is a type mismatch" do
|
169
|
+
lambda { subject.send add_method, Person.new(:name => "Foo", :age => 2) }.should raise_error MassiveRecord::ORM::RelationTypeMismatch
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should not save the pushed proxy_target if proxy_owner is not persisted" do
|
173
|
+
proxy_owner.should_receive(:persisted?).and_return false
|
174
|
+
proxy_target.should_not_receive(:save)
|
175
|
+
subject.send(add_method, proxy_target)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should not save the proxy_owner object if it has not been persisted before" do
|
179
|
+
proxy_owner.should_receive(:persisted?).and_return false
|
180
|
+
proxy_owner.should_not_receive(:save)
|
181
|
+
subject.send(add_method, proxy_target)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should save the pushed proxy_target if proxy_owner is persisted" do
|
185
|
+
proxy_owner.save!
|
186
|
+
proxy_target.should_receive(:save).and_return(true)
|
187
|
+
subject.send(add_method, proxy_target)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should not save anything if one record is invalid" do
|
191
|
+
proxy_owner.save!
|
192
|
+
|
193
|
+
proxy_target.should_receive(:valid?).and_return(true)
|
194
|
+
proxy_target_2.should_receive(:valid?).and_return(false)
|
195
|
+
|
196
|
+
proxy_target.should_not_receive(:save)
|
197
|
+
proxy_target_2.should_not_receive(:save)
|
198
|
+
proxy_owner.should_not_receive(:save)
|
199
|
+
|
200
|
+
subject.send(add_method, [proxy_target, proxy_target_2]).should be_false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "removing records from the collection" do
|
207
|
+
[:destroy, :delete].each do |delete_method|
|
208
|
+
describe "with ##{delete_method}" do
|
209
|
+
before do
|
210
|
+
subject << proxy_target
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not be in proxy after being removed" do
|
214
|
+
subject.send(delete_method, proxy_target)
|
215
|
+
subject.proxy_target.should_not include proxy_target
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should remove the destroyed records id from proxy_owner foreign keys" do
|
219
|
+
subject.send(delete_method, proxy_target)
|
220
|
+
proxy_owner.test_class_ids.should_not include(proxy_target.id)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should not remove foreign keys in proxy_owner if it does not respond to it" do
|
224
|
+
proxy_owner.should_receive(:respond_to?).and_return false
|
225
|
+
subject.send(delete_method, proxy_target)
|
226
|
+
proxy_owner.test_class_ids.should include(proxy_target.id)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should not save the proxy_owner if it has not been persisted" do
|
230
|
+
proxy_owner.should_receive(:persisted?).and_return(false)
|
231
|
+
proxy_owner.should_not_receive(:save)
|
232
|
+
subject.send(delete_method, proxy_target)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should save the proxy_owner if it has been persisted" do
|
236
|
+
proxy_owner.save!
|
237
|
+
proxy_owner.should_receive(:save)
|
238
|
+
subject.send(delete_method, proxy_target)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "with #destroy" do
|
244
|
+
before do
|
245
|
+
subject << proxy_target
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should ask the record to destroy self" do
|
249
|
+
proxy_target.should_receive(:destroy)
|
250
|
+
subject.destroy proxy_target
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "with #delete" do
|
255
|
+
before do
|
256
|
+
subject << proxy_target
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should not ask the record to destroy self" do
|
260
|
+
proxy_target.should_not_receive(:destroy)
|
261
|
+
proxy_target.should_not_receive(:delete)
|
262
|
+
subject.delete(proxy_target)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
|
268
|
+
describe "with destroy_all" do
|
269
|
+
before do
|
270
|
+
proxy_owner.save!
|
271
|
+
subject << proxy_target << proxy_target_2
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should not include any records after destroying all" do
|
275
|
+
subject.destroy_all
|
276
|
+
subject.proxy_target.should be_empty
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should remove all foreign keys in proxy_owner" do
|
280
|
+
subject.destroy_all
|
281
|
+
proxy_owner.test_class_ids.should be_empty
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should call reset after all destroyed" do
|
285
|
+
subject.should_receive(:reset)
|
286
|
+
subject.destroy_all
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should be loaded after all being destroyed" do
|
290
|
+
subject.destroy_all
|
291
|
+
should be_loaded
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should call destroy on each record" do
|
295
|
+
proxy_target.should_receive(:destroy)
|
296
|
+
proxy_target_2.should_receive(:destroy)
|
297
|
+
subject.destroy_all
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "with delete_all" do
|
302
|
+
before do
|
303
|
+
proxy_owner.save!
|
304
|
+
subject << proxy_target << proxy_target_2
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should not include any records after destroying all" do
|
308
|
+
subject.delete_all
|
309
|
+
subject.proxy_target.should be_empty
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should remove all foreign keys in proxy_owner" do
|
313
|
+
subject.delete_all
|
314
|
+
proxy_owner.test_class_ids.should be_empty
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should call reset after all destroyed" do
|
318
|
+
subject.should_receive(:reset)
|
319
|
+
subject.delete_all
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should be loaded after all being destroyed" do
|
323
|
+
subject.delete_all
|
324
|
+
should be_loaded
|
325
|
+
end
|
326
|
+
|
327
|
+
it "should not call destroy on each record" do
|
328
|
+
proxy_target.should_not_receive(:destroy)
|
329
|
+
proxy_target_2.should_not_receive(:destroy)
|
330
|
+
subject.delete_all
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
[:length, :size, :count].each do |method|
|
336
|
+
describe "##{method}" do
|
337
|
+
[true, false].each do |should_persist_proxy_owner|
|
338
|
+
describe "with proxy_owner " + (should_persist_proxy_owner ? "persisted" : "not persisted") do
|
339
|
+
before do
|
340
|
+
proxy_owner.save! if should_persist_proxy_owner
|
341
|
+
subject << proxy_target
|
342
|
+
end
|
343
|
+
|
344
|
+
it "should return the correct #{method} when loaded" do
|
345
|
+
subject.reload if should_persist_proxy_owner
|
346
|
+
subject.send(method).should == 1
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should return the correct #{method} when not loaded" do
|
350
|
+
subject.reset if should_persist_proxy_owner
|
351
|
+
subject.send(method).should == 1
|
352
|
+
end
|
353
|
+
|
354
|
+
it "should return the correct #{method} when a record is added" do
|
355
|
+
subject << proxy_target_2
|
356
|
+
subject.send(method).should == 2
|
357
|
+
end
|
358
|
+
|
359
|
+
it "should return the correct #{method} when a record is added to an unloaded proxy" do
|
360
|
+
subject.reset if should_persist_proxy_owner
|
361
|
+
subject << proxy_target_2
|
362
|
+
subject.send(method).should == 2
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
describe "#include" do
|
370
|
+
[true, false].each do |should_persist_proxy_owner|
|
371
|
+
describe "with proxy_owner " + (should_persist_proxy_owner ? "persisted" : "not persisted") do
|
372
|
+
before do
|
373
|
+
proxy_owner.save! if should_persist_proxy_owner
|
374
|
+
subject << proxy_target
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should return that it includes it's proxy_target when loaded" do
|
378
|
+
subject.reload if should_persist_proxy_owner
|
379
|
+
should include proxy_target
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should return that it includes it's proxy_target when not loaded" do
|
383
|
+
subject.reset if should_persist_proxy_owner
|
384
|
+
should include proxy_target
|
385
|
+
end
|
386
|
+
|
387
|
+
it "should return that it includes it's proxy_target when a record is added" do
|
388
|
+
subject << proxy_target_2
|
389
|
+
should include proxy_target, proxy_target_2
|
390
|
+
end
|
391
|
+
|
392
|
+
it "should return that it includes it's proxy_target when a record is added to an unloaded proxy" do
|
393
|
+
subject.reset if should_persist_proxy_owner
|
394
|
+
subject << proxy_target_2
|
395
|
+
should include proxy_target, proxy_target_2
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
|
402
|
+
|
403
|
+
describe "#first" do
|
404
|
+
describe "stored foreign keys" do
|
405
|
+
before do
|
406
|
+
proxy_owner.save!
|
407
|
+
subject << proxy_target << proxy_target_2
|
408
|
+
subject.reset
|
409
|
+
end
|
410
|
+
|
411
|
+
it "should return nil if no relations are found" do
|
412
|
+
subject.destroy_all
|
413
|
+
subject.first.should be_nil
|
414
|
+
end
|
415
|
+
|
416
|
+
it "should return the first proxy_target" do
|
417
|
+
subject.first.should == proxy_target
|
418
|
+
end
|
419
|
+
|
420
|
+
it "should not be loaded" do
|
421
|
+
subject.first
|
422
|
+
subject.should_not be_loaded
|
423
|
+
end
|
424
|
+
|
425
|
+
it "should just find the first foreign key" do
|
426
|
+
TestClass.should_receive(:find).with(proxy_target.id, anything).and_return(proxy_target)
|
427
|
+
subject.first
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
describe "with records_starts_from (proc)" do
|
432
|
+
let(:proxy_target) { Person.new :id => proxy_owner.id+"-friend-1", :name => "T", :age => 2 }
|
433
|
+
let(:proxy_target_2) { Person.new :id => proxy_owner.id+"-friend-2", :name => "H", :age => 9 }
|
434
|
+
let(:metadata) { subject.metadata }
|
435
|
+
|
436
|
+
subject { proxy_owner.send(:relation_proxy, 'friends') }
|
437
|
+
|
438
|
+
before do
|
439
|
+
proxy_owner.save!
|
440
|
+
subject << proxy_target << proxy_target_2
|
441
|
+
subject.reset
|
442
|
+
end
|
443
|
+
|
444
|
+
it "should return nil if no relations are found" do
|
445
|
+
subject.destroy_all
|
446
|
+
subject.first.should be_nil
|
447
|
+
end
|
448
|
+
|
449
|
+
it "should return the first proxy_target" do
|
450
|
+
subject.first.should == proxy_target
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should not be loaded" do
|
454
|
+
subject.first
|
455
|
+
subject.should_not be_loaded
|
456
|
+
end
|
457
|
+
|
458
|
+
it "should find the first with a limit" do
|
459
|
+
Person.should_receive(:all).with(hash_including(:limit => 1))
|
460
|
+
subject.first
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
|
466
|
+
describe "#find" do
|
467
|
+
let(:not_among_targets) { proxy_target_3 }
|
468
|
+
|
469
|
+
describe "stored foreign keys" do
|
470
|
+
before do
|
471
|
+
proxy_owner.save!
|
472
|
+
subject << proxy_target << proxy_target_2
|
473
|
+
subject.reset
|
474
|
+
|
475
|
+
not_among_targets.save!
|
476
|
+
end
|
477
|
+
|
478
|
+
it "should find the object from database if id exists among foreig keys" do
|
479
|
+
subject.find(proxy_target.id).should == proxy_target
|
480
|
+
end
|
481
|
+
|
482
|
+
it "should raise error if record is not among records in association" do
|
483
|
+
lambda { subject.find(not_among_targets.id) }.should raise_error MassiveRecord::ORM::RecordNotFound
|
484
|
+
end
|
485
|
+
|
486
|
+
it "should not hit database if proxy has been loaded" do
|
487
|
+
subject.load_proxy_target
|
488
|
+
TestClass.should_not_receive(:find)
|
489
|
+
subject.find(proxy_target.id).should == proxy_target
|
490
|
+
end
|
491
|
+
|
492
|
+
it "should raise error if proxy is loaded, but record is not found in association" do
|
493
|
+
subject.load_proxy_target
|
494
|
+
lambda { subject.find(not_among_targets.id) }.should raise_error MassiveRecord::ORM::RecordNotFound
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
|
499
|
+
describe "with records_starts_from (proc)" do
|
500
|
+
let(:proxy_target) { Person.new :id => proxy_owner.id+"-friend-1", :name => "T", :age => 2 }
|
501
|
+
let(:proxy_target_2) { Person.new :id => proxy_owner.id+"-friend-2", :name => "H", :age => 9 }
|
502
|
+
let(:not_among_targets) { Person.new :id => "NOT-friend-1", :name => "H", :age => 9 }
|
503
|
+
let(:metadata) { subject.metadata }
|
504
|
+
|
505
|
+
subject { proxy_owner.send(:relation_proxy, 'friends') }
|
506
|
+
|
507
|
+
before do
|
508
|
+
proxy_owner.save!
|
509
|
+
subject << proxy_target << proxy_target_2
|
510
|
+
subject.reset
|
511
|
+
|
512
|
+
not_among_targets.save!
|
513
|
+
end
|
514
|
+
|
515
|
+
|
516
|
+
it "should find the object from database if id exists among foreig keys" do
|
517
|
+
subject.find(proxy_target.id).should == proxy_target
|
518
|
+
end
|
519
|
+
|
520
|
+
it "should raise error if record is not among records in association" do
|
521
|
+
lambda { subject.find(not_among_targets.id) }.should raise_error MassiveRecord::ORM::RecordNotFound
|
522
|
+
end
|
523
|
+
|
524
|
+
|
525
|
+
|
526
|
+
it "should not hit database if proxy has been loaded" do
|
527
|
+
subject.load_proxy_target
|
528
|
+
Person.should_not_receive(:find)
|
529
|
+
subject.find(proxy_target.id).should == proxy_target
|
530
|
+
end
|
531
|
+
|
532
|
+
it "should raise error if proxy is loaded, but record is not found in association" do
|
533
|
+
subject.load_proxy_target
|
534
|
+
lambda { subject.find(not_among_targets.id) }.should raise_error MassiveRecord::ORM::RecordNotFound
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
|
540
|
+
|
541
|
+
describe "#limit" do
|
542
|
+
let(:not_among_targets) { proxy_target_3 }
|
543
|
+
|
544
|
+
describe "stored foreign keys" do
|
545
|
+
before do
|
546
|
+
proxy_owner.save!
|
547
|
+
subject << proxy_target << proxy_target_2
|
548
|
+
subject.reset
|
549
|
+
|
550
|
+
not_among_targets.save!
|
551
|
+
end
|
552
|
+
|
553
|
+
it "should return empty array if no targets are found" do
|
554
|
+
subject.destroy_all
|
555
|
+
subject.limit(1).should be_empty
|
556
|
+
end
|
557
|
+
|
558
|
+
|
559
|
+
it "should do db query with a limited set of ids" do
|
560
|
+
subject.limit(1).should == [proxy_target]
|
561
|
+
end
|
562
|
+
|
563
|
+
it "should not be loaded after a limit query" do
|
564
|
+
subject.limit(1).should == [proxy_target]
|
565
|
+
subject.should_not be_loaded
|
566
|
+
end
|
567
|
+
|
568
|
+
it "should not hit the database if the proxy is loaded" do
|
569
|
+
subject.load_proxy_target
|
570
|
+
TestClass.should_not_receive(:find)
|
571
|
+
subject.limit(1)
|
572
|
+
end
|
573
|
+
|
574
|
+
it "should return correct result set if proxy is loaded" do
|
575
|
+
subject.load_proxy_target
|
576
|
+
subject.limit(1).should == [proxy_target]
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
|
581
|
+
describe "with records_starts_from (proc)" do
|
582
|
+
let(:proxy_target) { Person.new :id => proxy_owner.id+"-friend-1", :name => "T", :age => 2 }
|
583
|
+
let(:proxy_target_2) { Person.new :id => proxy_owner.id+"-friend-2", :name => "H", :age => 9 }
|
584
|
+
let(:not_among_targets) { Person.new :id => "NOT-friend-1", :name => "H", :age => 9 }
|
585
|
+
let(:metadata) { subject.metadata }
|
586
|
+
|
587
|
+
subject { proxy_owner.send(:relation_proxy, 'friends') }
|
588
|
+
|
589
|
+
before do
|
590
|
+
proxy_owner.save!
|
591
|
+
subject << proxy_target << proxy_target_2
|
592
|
+
subject.reset
|
593
|
+
|
594
|
+
not_among_targets.save!
|
595
|
+
end
|
596
|
+
|
597
|
+
it "should return empty array if no targets are found" do
|
598
|
+
subject.destroy_all
|
599
|
+
subject.limit(1).should be_empty
|
600
|
+
end
|
601
|
+
|
602
|
+
|
603
|
+
it "should do db query with a limited set of ids" do
|
604
|
+
subject.limit(1).should == [proxy_target]
|
605
|
+
end
|
606
|
+
|
607
|
+
it "should not be loaded after a limit query" do
|
608
|
+
subject.limit(1).should == [proxy_target]
|
609
|
+
subject.should_not be_loaded
|
610
|
+
end
|
611
|
+
|
612
|
+
it "should not hit the database if the proxy is loaded" do
|
613
|
+
subject.load_proxy_target
|
614
|
+
Person.should_not_receive(:find)
|
615
|
+
subject.limit(1)
|
616
|
+
end
|
617
|
+
|
618
|
+
it "should return correct result set if proxy is loaded" do
|
619
|
+
subject.load_proxy_target
|
620
|
+
subject.limit(1).should == [proxy_target]
|
621
|
+
end
|
622
|
+
end
|
623
|
+
end
|
624
|
+
end
|