active_force 0.6.1 → 0.7.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +43 -17
- data/lib/active_attr/dirty.rb +3 -0
- data/lib/active_force/active_query.rb +32 -2
- data/lib/active_force/association.rb +14 -10
- data/lib/active_force/association/association.rb +26 -11
- data/lib/active_force/association/belongs_to_association.rb +1 -4
- data/lib/active_force/association/eager_load_projection_builder.rb +60 -0
- data/lib/active_force/association/has_many_association.rb +15 -5
- data/lib/active_force/association/relation_model_builder.rb +70 -0
- data/lib/active_force/attribute.rb +30 -0
- data/lib/active_force/mapping.rb +78 -0
- data/lib/active_force/query.rb +2 -8
- data/lib/active_force/sobject.rb +79 -95
- data/lib/active_force/table.rb +6 -2
- data/lib/active_force/version.rb +1 -1
- data/lib/generators/active_force/model/model_generator.rb +1 -0
- data/lib/generators/active_force/model/templates/model.rb.erb +0 -2
- data/spec/active_force/active_query_spec.rb +39 -12
- data/spec/active_force/association/relation_model_builder_spec.rb +62 -0
- data/spec/active_force/association_spec.rb +53 -88
- data/spec/active_force/attribute_spec.rb +27 -0
- data/spec/active_force/callbacks_spec.rb +1 -23
- data/spec/active_force/mapping_spec.rb +18 -0
- data/spec/active_force/query_spec.rb +32 -54
- data/spec/active_force/sobject/includes_spec.rb +290 -0
- data/spec/active_force/sobject/table_name_spec.rb +0 -21
- data/spec/active_force/sobject_spec.rb +212 -29
- data/spec/active_force/table_spec.rb +0 -3
- data/spec/fixtures/sobject/single_sobject_hash.yml +2 -0
- data/spec/spec_helper.rb +10 -4
- data/spec/support/restforce_factories.rb +9 -0
- data/spec/support/sobjects.rb +97 -0
- data/spec/support/whizbang.rb +25 -7
- metadata +18 -2
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::Attribute do
|
4
|
+
let(:attribute) { ActiveForce::Attribute }
|
5
|
+
|
6
|
+
describe 'initialize' do
|
7
|
+
let(:some_field) { attribute.new(:some_field) }
|
8
|
+
|
9
|
+
it 'should set "from" and "as" as default' do
|
10
|
+
expect(some_field.sfdc_name).to eq 'Some_Field__c'
|
11
|
+
expect(some_field.as).to eq :string
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should take values from the option parameter' do
|
15
|
+
other_field = attribute.new(:other_field, sfdc_name: 'OT__c', as: :integer)
|
16
|
+
expect(other_field.sfdc_name).to eq 'OT__c'
|
17
|
+
expect(other_field.as).to eq :integer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'when the attribute is' do
|
22
|
+
it 'a multipick should return all values as 1 string separated with ";"' do
|
23
|
+
names = attribute.new(:names, as: :multi_picklist)
|
24
|
+
expect(names.value_for_hash ['olvap', 'eloy']).to eq 'olvap;eloy'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'active_force/sobject'
|
3
2
|
|
4
3
|
describe ActiveForce::SObject do
|
5
4
|
let(:client) { double 'Client', create!: 'id' }
|
@@ -9,29 +8,8 @@ describe ActiveForce::SObject do
|
|
9
8
|
end
|
10
9
|
|
11
10
|
describe "save" do
|
12
|
-
|
13
11
|
it 'call action callback when save a record' do
|
14
|
-
|
15
|
-
|
16
|
-
field :updated_from
|
17
|
-
field :dirty_attribute
|
18
|
-
|
19
|
-
before_save :set_as_updated_from_rails
|
20
|
-
after_save :mark_dirty
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def set_as_updated_from_rails
|
25
|
-
self.updated_from = 'Rails'
|
26
|
-
end
|
27
|
-
|
28
|
-
def mark_dirty
|
29
|
-
self.dirty_attribute = true
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
whizbanged = Whizbanged.new
|
12
|
+
whizbanged = Whizbang.new
|
35
13
|
whizbanged.save
|
36
14
|
expect(whizbanged.updated_from).to eq 'Rails'
|
37
15
|
expect(whizbanged.dirty_attribute).to eq true
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::Mapping do
|
4
|
+
let(:mapping){ ActiveForce::Mapping.new 'some_table' }
|
5
|
+
|
6
|
+
describe 'field' do
|
7
|
+
it 'should add a new attribute to the instance' do
|
8
|
+
mapping.field :id, from: 'Id'
|
9
|
+
expect(mapping.mappings).to eq({ id: 'Id' })
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sf_names should return all attributes names from salesforce' do
|
13
|
+
mapping.field :id, from: 'Id'
|
14
|
+
mapping.field :name, from: 'Name'
|
15
|
+
expect(mapping.sfdc_names).to eq ['Id', 'Name']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,148 +1,126 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'active_force/query'
|
3
2
|
|
4
3
|
describe ActiveForce::Query do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
after do
|
4
|
+
let(:query) do
|
5
|
+
query = ActiveForce::Query.new 'table_name'
|
6
|
+
query.fields ['name', 'etc']
|
7
|
+
query
|
12
8
|
end
|
13
9
|
|
14
10
|
describe '.select' do
|
15
11
|
it 'use column sent on the select method' do
|
16
|
-
expect(
|
12
|
+
expect(query.select('name').all.to_s).to eq "SELECT name FROM table_name"
|
17
13
|
end
|
18
14
|
|
19
15
|
it 'use columns sent on the select method' do
|
20
|
-
expect(
|
16
|
+
expect(query.select(['id','name']).all.to_s).to eq "SELECT id, name FROM table_name"
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
20
|
describe ".all" do
|
25
21
|
it "table should return table name" do
|
26
|
-
expect(
|
22
|
+
expect(query.all.table).to eq(query.table)
|
27
23
|
end
|
28
24
|
|
29
25
|
it "fields should return fields" do
|
30
|
-
expect(
|
26
|
+
expect(query.all.fields).to eq query.fields
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
30
|
describe ".all.to_s" do
|
35
31
|
it "should return a query for all records" do
|
36
|
-
expect(
|
32
|
+
expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
|
37
33
|
end
|
38
34
|
|
39
35
|
it "should ignore dupicated attributes in select statment" do
|
40
|
-
|
41
|
-
expect(
|
36
|
+
query.fields ['Id', 'name', 'etc']
|
37
|
+
expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
|
42
38
|
end
|
43
39
|
end
|
44
40
|
|
45
41
|
describe ".where" do
|
46
42
|
it "should add a where condition to a query" do
|
47
|
-
expect(
|
43
|
+
expect(query.where("name like '%a%'").to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (name like '%a%')"
|
48
44
|
end
|
49
45
|
|
50
|
-
it "should add multiples conditions to a query" do
|
51
|
-
expect(
|
46
|
+
it "should add multiples conditions to a query with parentheses" do
|
47
|
+
expect(query.where("condition1 = 1").where("condition2 = 2 OR condition3 = 3").to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) AND (condition2 = 2 OR condition3 = 3)"
|
52
48
|
end
|
53
49
|
end
|
54
50
|
|
55
51
|
describe ".limit" do
|
56
52
|
it "should add a limit to a query" do
|
57
|
-
expect(
|
53
|
+
expect(query.limit("25").to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
|
58
54
|
end
|
59
55
|
end
|
60
56
|
|
61
57
|
describe ".limit_value" do
|
62
58
|
it "should return the limit value" do
|
63
|
-
|
64
|
-
expect(
|
59
|
+
query.limit(4)
|
60
|
+
expect(query.limit_value).to eq 4
|
65
61
|
end
|
66
62
|
end
|
67
63
|
|
68
64
|
describe ".offset" do
|
69
65
|
it "should add an offset to a query" do
|
70
|
-
expect(
|
66
|
+
expect(query.offset(4).to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
|
71
67
|
end
|
72
68
|
end
|
73
69
|
|
74
70
|
describe ".offset_value" do
|
75
71
|
it "should return the offset value" do
|
76
|
-
|
77
|
-
expect(
|
72
|
+
query.offset(4)
|
73
|
+
expect(query.offset_value).to eq 4
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
81
77
|
describe ".find.to_s" do
|
82
78
|
it "should return a query for 1 record" do
|
83
|
-
expect(
|
79
|
+
expect(query.find(2).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (Id = '2') LIMIT 1"
|
84
80
|
end
|
85
81
|
end
|
86
82
|
|
87
83
|
describe ".order" do
|
88
84
|
it "should add a order condition in the statment" do
|
89
|
-
expect(
|
85
|
+
expect(query.order("name desc").to_s).to eq "SELECT Id, name, etc FROM table_name ORDER BY name desc"
|
90
86
|
end
|
91
87
|
|
92
88
|
it "should add a order condition in the statment with WHERE and LIMIT" do
|
93
|
-
expect(
|
89
|
+
expect(query.where("condition1 = 1").order("name desc").limit(1).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) ORDER BY name desc LIMIT 1"
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
97
93
|
describe '.join' do
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
94
|
+
let(:join_query) do
|
95
|
+
join = ActiveForce::Query.new 'join_table_name'
|
96
|
+
join.fields ['name', 'etc']
|
97
|
+
join
|
102
98
|
end
|
103
99
|
|
104
100
|
it 'should add another select statment on the current select' do
|
105
|
-
expect(
|
101
|
+
expect(query.join(join_query).to_s).to eq 'SELECT Id, name, etc, (SELECT Id, name, etc FROM join_table_name) FROM table_name'
|
106
102
|
end
|
107
103
|
end
|
108
104
|
|
109
105
|
describe '.first' do
|
110
106
|
it 'should return the query for the first record' do
|
111
|
-
expect(
|
107
|
+
expect(query.first.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
|
112
108
|
end
|
113
109
|
end
|
114
110
|
|
115
111
|
describe '.last' do
|
116
112
|
it 'should return the query for the last record' do
|
117
|
-
expect(
|
113
|
+
expect(query.last.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
|
118
114
|
end
|
119
115
|
end
|
120
116
|
|
121
117
|
describe ".count" do
|
122
118
|
it "should return the query for getting the row count" do
|
123
|
-
expect(
|
119
|
+
expect(query.count.to_s).to eq 'SELECT count(Id) FROM table_name'
|
124
120
|
end
|
125
121
|
|
126
122
|
it "should work with a condition" do
|
127
|
-
expect(
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe '.options' do
|
132
|
-
it 'should add a where if the option has a where condition' do
|
133
|
-
expect(@query.options(where: 'var = 1').to_s).to eq "SELECT Id, name, etc FROM table_name WHERE var = 1"
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'should add a limit if the option has a limit condition' do
|
137
|
-
expect(@query.options(limit: 1).to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 1"
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should add a order if the option has a order condition' do
|
141
|
-
expect(@query.options(order: 'name desc').to_s).to eq "SELECT Id, name, etc FROM table_name ORDER BY name desc"
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'should work with multiples options' do
|
145
|
-
expect(@query.options(where: 'var = 1', order: 'name desc', limit: 1).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE var = 1 ORDER BY name desc LIMIT 1"
|
123
|
+
expect(query.where("name = 'cool'").count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
|
146
124
|
end
|
147
125
|
end
|
148
126
|
end
|
@@ -0,0 +1,290 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ActiveForce
|
4
|
+
describe SObject do
|
5
|
+
let(:client){ double "client" }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(ActiveForce::SObject).to receive(:sfdc_client).and_return client
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.includes' do
|
12
|
+
context 'belongs_to' do
|
13
|
+
it 'queries the API for the associated record' do
|
14
|
+
soql = Territory.includes(:quota).where(id: '123').to_s
|
15
|
+
expect(soql).to eq "SELECT Id, Quota__c, Name, Quota__r.Bar_Id__c FROM Territory WHERE (Id = '123')"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "queries the API once to retrieve the object and its related one" do
|
19
|
+
response = [build_restforce_sobject({
|
20
|
+
"Id" => "123",
|
21
|
+
"Quota__c" => "321",
|
22
|
+
"Quota__r" => {
|
23
|
+
"Bar_Id__c" => "321"
|
24
|
+
}
|
25
|
+
})]
|
26
|
+
allow(client).to receive(:query).once.and_return response
|
27
|
+
territory = Territory.includes(:quota).find "123"
|
28
|
+
expect(territory.quota).to be_a Quota
|
29
|
+
expect(territory.quota.id).to eq "321"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "queries the API once to retrieve the object and its related one" do
|
33
|
+
response = [build_restforce_sobject({
|
34
|
+
"Id" => "123",
|
35
|
+
"Quota__c" => "321",
|
36
|
+
"Quota__r" => {
|
37
|
+
"Bar_Id__c" => "321"
|
38
|
+
}
|
39
|
+
})]
|
40
|
+
allow(client).to receive(:query).once.and_return response
|
41
|
+
territory = Territory.includes(:quota).find "123"
|
42
|
+
expect(territory.quota).to be_a Quota
|
43
|
+
expect(territory.quota.id).to eq "321"
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with namespaced SObjects' do
|
47
|
+
it 'queries the API for the associated record' do
|
48
|
+
soql = Salesforce::Territory.includes(:quota).where(id: '123').to_s
|
49
|
+
expect(soql).to eq "SELECT Id, QuotaId, WidgetId, Quota__r.Id FROM Territory WHERE (Id = '123')"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "queries the API once to retrieve the object and its related one" do
|
53
|
+
response = [build_restforce_sobject({
|
54
|
+
"Id" => "123",
|
55
|
+
"QuotaId" => "321",
|
56
|
+
"WidgetId" => "321",
|
57
|
+
"Quota__r" => {
|
58
|
+
"Id" => "321"
|
59
|
+
}
|
60
|
+
})]
|
61
|
+
allow(client).to receive(:query).once.and_return response
|
62
|
+
territory = Salesforce::Territory.includes(:quota).find "123"
|
63
|
+
expect(territory.quota).to be_a Salesforce::Quota
|
64
|
+
expect(territory.quota.id).to eq "321"
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when the relationship table name is different from the actual table name' do
|
68
|
+
it 'formulates the correct SOQL' do
|
69
|
+
soql = Salesforce::Opportunity.includes(:owner).where(id: '123').to_s
|
70
|
+
expect(soql).to eq "SELECT Id, OwnerId, AccountId, Business_Partner__c, Owner.Id FROM Opportunity WHERE (Id = '123')"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "queries the API once to retrieve the object and its related one" do
|
74
|
+
response = [build_restforce_sobject({
|
75
|
+
"Id" => "123",
|
76
|
+
"OwnerId" => "321",
|
77
|
+
"AccountId" => "432",
|
78
|
+
"Owner" => {
|
79
|
+
"Id" => "321"
|
80
|
+
}
|
81
|
+
})]
|
82
|
+
allow(client).to receive(:query).once.and_return response
|
83
|
+
opportunity = Salesforce::Opportunity.includes(:owner).find "123"
|
84
|
+
expect(opportunity.owner).to be_a Salesforce::User
|
85
|
+
expect(opportunity.owner.id).to eq "321"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when the class name does not match the SFDC entity name' do
|
90
|
+
let(:expected_soql) do
|
91
|
+
"SELECT Id, QuotaId, WidgetId, Tegdiw__r.Id FROM Territory WHERE (Id = '123')"
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'queries the API for the associated record' do
|
95
|
+
soql = Salesforce::Territory.includes(:widget).where(id: '123').to_s
|
96
|
+
expect(soql).to eq expected_soql
|
97
|
+
end
|
98
|
+
|
99
|
+
it "queries the API once to retrieve the object and its related one" do
|
100
|
+
response = [build_restforce_sobject({
|
101
|
+
"Id" => "123",
|
102
|
+
"WidgetId" => "321",
|
103
|
+
"Tegdiw__r" => {
|
104
|
+
"Id" => "321"
|
105
|
+
}
|
106
|
+
})]
|
107
|
+
expected = expected_soql + ' LIMIT 1'
|
108
|
+
allow(client).to receive(:query).once.with(expected).and_return response
|
109
|
+
territory = Salesforce::Territory.includes(:widget).find "123"
|
110
|
+
expect(territory.widget).to be_a Salesforce::Widget
|
111
|
+
expect(territory.widget.id).to eq "321"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'child to several parents' do
|
116
|
+
it 'queries the API for associated records' do
|
117
|
+
soql = Salesforce::Territory.includes(:quota, :widget).where(id: '123').to_s
|
118
|
+
expect(soql).to eq "SELECT Id, QuotaId, WidgetId, Quota__r.Id, Tegdiw__r.Id FROM Territory WHERE (Id = '123')"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "queries the API once to retrieve the object and its assocations" do
|
122
|
+
response = [build_restforce_sobject({
|
123
|
+
"Id" => "123",
|
124
|
+
"QuotaId" => "321",
|
125
|
+
"WidgetId" => "321",
|
126
|
+
"Quota__r" => {
|
127
|
+
"Id" => "321"
|
128
|
+
},
|
129
|
+
"Tegdiw__r" => {
|
130
|
+
"Id" => "321"
|
131
|
+
}
|
132
|
+
})]
|
133
|
+
allow(client).to receive(:query).once.and_return response
|
134
|
+
territory = Salesforce::Territory.includes(:quota, :widget).find "123"
|
135
|
+
expect(territory.quota).to be_a Salesforce::Quota
|
136
|
+
expect(territory.quota.id).to eq "321"
|
137
|
+
expect(territory.widget).to be_a Salesforce::Widget
|
138
|
+
expect(territory.widget.id).to eq "321"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'when there is no associated record' do
|
144
|
+
it "queries the API once to retrieve the object and its related one" do
|
145
|
+
response = [build_restforce_sobject({
|
146
|
+
"Id" => "123",
|
147
|
+
"Quota__c" => "321",
|
148
|
+
"Quota__r" => nil
|
149
|
+
})]
|
150
|
+
allow(client).to receive(:query).once.and_return response
|
151
|
+
territory = Territory.includes(:quota).find "123"
|
152
|
+
expect(territory.quota).to be_nil
|
153
|
+
expect(territory.quota).to be_nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'has_many' do
|
159
|
+
context 'with standard objects' do
|
160
|
+
it 'formulates the correct SOQL query' do
|
161
|
+
soql = Account.includes(:opportunities).where(id: '123').to_s
|
162
|
+
expect(soql).to eq "SELECT Id, OwnerId, (SELECT Id, AccountId FROM Opportunities) FROM Account WHERE (Id = '123')"
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'builds the associated objects and caches them' do
|
166
|
+
response = [build_restforce_sobject({
|
167
|
+
'Id' => '123',
|
168
|
+
'Opportunities' => build_restforce_collection([
|
169
|
+
{'Id' => '213', 'AccountId' => '123'},
|
170
|
+
{'Id' => '214', 'AccountId' => '123'}
|
171
|
+
])
|
172
|
+
})]
|
173
|
+
allow(client).to receive(:query).once.and_return response
|
174
|
+
account = Account.includes(:opportunities).find '123'
|
175
|
+
expect(account.opportunities).to be_an Array
|
176
|
+
expect(account.opportunities.all? { |o| o.is_a? Opportunity }).to eq true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'with custom objects' do
|
181
|
+
it 'formulates the correct SOQL query' do
|
182
|
+
soql = Quota.includes(:prez_clubs).where(id: '123').to_s
|
183
|
+
expect(soql).to eq "SELECT Id, Bar_Id__c, (SELECT Id, QuotaId FROM PrezClubs__r) FROM Quota__c WHERE (Bar_Id__c = '123')"
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'builds the associated objects and caches them' do
|
187
|
+
response = [build_restforce_sobject({
|
188
|
+
'Id' => '123',
|
189
|
+
'PrezClubs__r' => build_restforce_collection([
|
190
|
+
{'Id' => '213', 'QuotaId' => '123'},
|
191
|
+
{'Id' => '214', 'QuotaId' => '123'}
|
192
|
+
])
|
193
|
+
})]
|
194
|
+
allow(client).to receive(:query).once.and_return response
|
195
|
+
account = Quota.includes(:prez_clubs).find '123'
|
196
|
+
expect(account.prez_clubs).to be_an Array
|
197
|
+
expect(account.prez_clubs.all? { |o| o.is_a? PrezClub }).to eq true
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'mixing standard and custom objects' do
|
202
|
+
it 'formulates the correct SOQL query' do
|
203
|
+
soql = Quota.includes(:territories, :prez_clubs).where(id: '123').to_s
|
204
|
+
expect(soql).to eq "SELECT Id, Bar_Id__c, (SELECT Id, Quota__c, Name FROM Territories), (SELECT Id, QuotaId FROM PrezClubs__r) FROM Quota__c WHERE (Bar_Id__c = '123')"
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'builds the associated objects and caches them' do
|
208
|
+
response = [build_restforce_sobject({
|
209
|
+
'Id' => '123',
|
210
|
+
'PrezClubs__r' => build_restforce_collection([
|
211
|
+
{'Id' => '213', 'QuotaId' => '123'},
|
212
|
+
{'Id' => '214', 'QuotaId' => '123'}
|
213
|
+
]),
|
214
|
+
'Territories' => build_restforce_collection([
|
215
|
+
{'Id' => '213', 'Quota__c' => '123'},
|
216
|
+
{'Id' => '214', 'Quota__c' => '123'}
|
217
|
+
])
|
218
|
+
})]
|
219
|
+
allow(client).to receive(:query).once.and_return response
|
220
|
+
account = Quota.includes(:territories, :prez_clubs).find '123'
|
221
|
+
expect(account.prez_clubs).to be_an Array
|
222
|
+
expect(account.prez_clubs.all? { |o| o.is_a? PrezClub }).to eq true
|
223
|
+
expect(account.territories).to be_an Array
|
224
|
+
expect(account.territories.all? { |o| o.is_a? Territory }).to eq true
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'with namespaced SObjects' do
|
229
|
+
it 'formulates the correct SOQL query' do
|
230
|
+
soql = Salesforce::Quota.includes(:prez_clubs).where(id: '123').to_s
|
231
|
+
expect(soql).to eq "SELECT Id, (SELECT Id, QuotaId FROM PrezClubs__r) FROM Quota__c WHERE (Id = '123')"
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'builds the associated objects and caches them' do
|
235
|
+
response = [build_restforce_sobject({
|
236
|
+
'Id' => '123',
|
237
|
+
'PrezClubs__r' => build_restforce_collection([
|
238
|
+
{'Id' => '213', 'QuotaId' => '123'},
|
239
|
+
{'Id' => '214', 'QuotaId' => '123'}
|
240
|
+
])
|
241
|
+
})]
|
242
|
+
allow(client).to receive(:query).once.and_return response
|
243
|
+
account = Salesforce::Quota.includes(:prez_clubs).find '123'
|
244
|
+
expect(account.prez_clubs).to be_an Array
|
245
|
+
expect(account.prez_clubs.all? { |o| o.is_a? Salesforce::PrezClub }).to eq true
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context 'when there are no associated records returned by the query' do
|
250
|
+
it 'caches the response' do
|
251
|
+
response = [build_restforce_sobject({
|
252
|
+
'Id' => '123',
|
253
|
+
'Opportunities' => nil
|
254
|
+
})]
|
255
|
+
allow(client).to receive(:query).once.and_return response
|
256
|
+
account = Account.includes(:opportunities).find '123'
|
257
|
+
expect(account.opportunities).to eq []
|
258
|
+
expect(account.opportunities).to eq []
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe 'mixing belongs_to and has_many' do
|
264
|
+
it 'formulates the correct SOQL query' do
|
265
|
+
soql = Account.includes(:opportunities, :owner).where(id: '123').to_s
|
266
|
+
expect(soql).to eq "SELECT Id, OwnerId, (SELECT Id, AccountId FROM Opportunities), Owner__r.Id FROM Account WHERE (Id = '123')"
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'builds the associated objects and caches them' do
|
270
|
+
response = [build_restforce_sobject({
|
271
|
+
'Id' => '123',
|
272
|
+
'Opportunities' => build_restforce_collection([
|
273
|
+
{'Id' => '213', 'AccountId' => '123'},
|
274
|
+
{'Id' => '214', 'AccountId' => '123'}
|
275
|
+
]),
|
276
|
+
'Owner__r' => {
|
277
|
+
'Id' => '321'
|
278
|
+
}
|
279
|
+
})]
|
280
|
+
allow(client).to receive(:query).once.and_return response
|
281
|
+
account = Account.includes(:opportunities).find '123'
|
282
|
+
expect(account.opportunities).to be_an Array
|
283
|
+
expect(account.opportunities.all? { |o| o.is_a? Opportunity }).to eq true
|
284
|
+
expect(account.owner).to be_a Owner
|
285
|
+
expect(account.owner.id).to eq '321'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|