openstax_active_force 1.0.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 +7 -0
- data/.gitignore +17 -0
- data/.mailmap +3 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +98 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +174 -0
- data/Rakefile +6 -0
- data/active_force.gemspec +30 -0
- data/lib/active_attr/dirty.rb +33 -0
- data/lib/active_force/active_query.rb +155 -0
- data/lib/active_force/association/association.rb +50 -0
- data/lib/active_force/association/belongs_to_association.rb +26 -0
- data/lib/active_force/association/eager_load_projection_builder.rb +60 -0
- data/lib/active_force/association/has_many_association.rb +33 -0
- data/lib/active_force/association/relation_model_builder.rb +70 -0
- data/lib/active_force/association.rb +28 -0
- data/lib/active_force/attribute.rb +30 -0
- data/lib/active_force/mapping.rb +78 -0
- data/lib/active_force/query.rb +110 -0
- data/lib/active_force/sobject.rb +210 -0
- data/lib/active_force/standard_types.rb +357 -0
- data/lib/active_force/table.rb +37 -0
- data/lib/active_force/version.rb +3 -0
- data/lib/active_force.rb +13 -0
- data/lib/generators/active_force/model/USAGE +8 -0
- data/lib/generators/active_force/model/model_generator.rb +62 -0
- data/lib/generators/active_force/model/templates/model.rb.erb +5 -0
- data/spec/active_force/active_query_spec.rb +178 -0
- data/spec/active_force/association/relation_model_builder_spec.rb +62 -0
- data/spec/active_force/association_spec.rb +157 -0
- data/spec/active_force/attribute_spec.rb +27 -0
- data/spec/active_force/callbacks_spec.rb +20 -0
- data/spec/active_force/mapping_spec.rb +18 -0
- data/spec/active_force/query_spec.rb +126 -0
- data/spec/active_force/sobject/includes_spec.rb +290 -0
- data/spec/active_force/sobject/table_name_spec.rb +27 -0
- data/spec/active_force/sobject_spec.rb +398 -0
- data/spec/active_force/table_spec.rb +25 -0
- data/spec/active_force_spec.rb +7 -0
- data/spec/fixtures/sobject/single_sobject_hash.yml +26 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/fixture_helpers.rb +45 -0
- data/spec/support/restforce_factories.rb +9 -0
- data/spec/support/sobjects.rb +97 -0
- data/spec/support/whizbang.rb +30 -0
- metadata +196 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ActiveForce
|
4
|
+
module Association
|
5
|
+
describe RelationModelBuilder do
|
6
|
+
let(:instance){ described_class.new association, value }
|
7
|
+
|
8
|
+
describe '#build_relation_model' do
|
9
|
+
context 'has_many' do
|
10
|
+
let(:association){ HasManyAssociation.new Post, :comments }
|
11
|
+
|
12
|
+
context 'with values' do
|
13
|
+
let(:value) do
|
14
|
+
build_restforce_collection([
|
15
|
+
Restforce::SObject.new({'Id' => '213', 'PostId' => '123'}),
|
16
|
+
Restforce::SObject.new({'Id' => '214', 'PostId' => '123'})
|
17
|
+
])
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns an array of Comments' do
|
21
|
+
comments = instance.build_relation_model
|
22
|
+
expect(comments).to be_a Array
|
23
|
+
expect(comments.all?{ |c| c.is_a? Comment }).to be true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'without values' do
|
28
|
+
let(:value){ nil }
|
29
|
+
|
30
|
+
it 'returns an empty array' do
|
31
|
+
comments = instance.build_relation_model
|
32
|
+
expect(comments).to be_a Array
|
33
|
+
expect(comments).to be_empty
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'belongs_to' do
|
39
|
+
let(:association){ BelongsToAssociation.new(Comment, :post) }
|
40
|
+
|
41
|
+
context 'with a value' do
|
42
|
+
let(:value) do
|
43
|
+
build_restforce_sobject 'Id' => '213'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns a post' do
|
47
|
+
expect(instance.build_relation_model).to be_a Post
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'without a value' do
|
52
|
+
let(:value){ nil }
|
53
|
+
|
54
|
+
it 'returns nil' do
|
55
|
+
expect(instance.build_relation_model).to be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::SObject do
|
4
|
+
let :post do
|
5
|
+
Post.new(id: "1", title: 'Ham')
|
6
|
+
end
|
7
|
+
|
8
|
+
let :comment do
|
9
|
+
Comment.new(id: "1", post_id: "1")
|
10
|
+
end
|
11
|
+
|
12
|
+
let :client do
|
13
|
+
double("sfdc_client", query: [Restforce::Mash.new("Id" => 1)])
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
ActiveForce.sfdc_client = client
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "has_many_query" do
|
21
|
+
it "should respond to relation method" do
|
22
|
+
expect(post).to respond_to(:comments)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a ActiveQuery object" do
|
26
|
+
expect(post.comments).to be_a ActiveForce::ActiveQuery
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'makes only one API call to fetch the associated object' do
|
30
|
+
expect(client).to receive(:query).once
|
31
|
+
post.comments.to_a
|
32
|
+
post.comments.to_a
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'to_s' do
|
36
|
+
it "should return a SOQL statment" do
|
37
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
|
38
|
+
expect(post.comments.to_s).to eq soql
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when the SObject is namespaced' do
|
43
|
+
let(:account){ Foo::Account.new(id: '1') }
|
44
|
+
|
45
|
+
it 'correctly infers the foreign key and forms the correct query' do
|
46
|
+
soql = "SELECT Id, AccountId, Partner_Account_Id__c FROM Opportunity WHERE (AccountId = '1')"
|
47
|
+
expect(account.opportunities.to_s).to eq soql
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'uses an explicit foreign key if it is supplied' do
|
51
|
+
soql = "SELECT Id, AccountId, Partner_Account_Id__c FROM Opportunity WHERE (Partner_Account_Id__c = '1')"
|
52
|
+
expect(account.partner_opportunities.to_s).to eq soql
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'has_many(options)' do
|
58
|
+
it 'should allow to send a different query table name' do
|
59
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
|
60
|
+
expect(post.ugly_comments.to_s).to eq soql
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should allow to change the foreign key' do
|
64
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PosterId__c = '1')"
|
65
|
+
expect(post.poster_comments.to_s).to eq soql
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should allow to add a where condition' do
|
69
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (1 = 0) AND (PostId = '1')"
|
70
|
+
expect(post.impossible_comments.to_s).to eq soql
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'accepts custom scoping' do
|
74
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (Body__c = 'RE: Ham') AND (PostId = '1') ORDER BY CreationDate DESC"
|
75
|
+
expect(post.reply_comments.to_s).to eq soql
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'accepts custom scoping that preloads associations of the association' do
|
79
|
+
account = Salesforce::Account.new id: '1', business_partner: 'qwerty'
|
80
|
+
soql = "SELECT Id, OwnerId, AccountId, Business_Partner__c, Owner.Id FROM Opportunity WHERE (Business_Partner__c = 'qwerty') AND (AccountId = '1')"
|
81
|
+
expect(account.partner_opportunities.to_s).to eq soql
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should use a convention name for the foreign key' do
|
85
|
+
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
|
86
|
+
expect(post.comments.to_s).to eq soql
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "belongs_to" do
|
91
|
+
it "should get the resource it belongs to" do
|
92
|
+
expect(comment.post).to be_instance_of(Post)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should allow to pass a foreign key as options" do
|
96
|
+
Comment.belongs_to :post, foreign_key: :fancy_post_id
|
97
|
+
allow(comment).to receive(:fancy_post_id).and_return "2"
|
98
|
+
expect(client).to receive(:query).with("SELECT Id, Title__c FROM Post__c WHERE (Id = '2') LIMIT 1")
|
99
|
+
comment.post
|
100
|
+
Comment.belongs_to :post # reset association to original value
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'makes only one API call to fetch the associated object' do
|
104
|
+
expect(client).to receive(:query).once
|
105
|
+
comment.post
|
106
|
+
comment.post
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "assignments" do
|
110
|
+
let(:comment) do
|
111
|
+
comment = Comment.new(id: '1')
|
112
|
+
comment.post = Post.new(id: '1')
|
113
|
+
comment
|
114
|
+
end
|
115
|
+
|
116
|
+
before do
|
117
|
+
expect(client).to_not receive(:query)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'accepts assignment of an existing object as an association' do
|
121
|
+
expect(client).to_not receive(:query)
|
122
|
+
other_post = Post.new(id: "2")
|
123
|
+
comment.post = other_post
|
124
|
+
expect(comment.post_id).to eq other_post.id
|
125
|
+
expect(comment.post).to eq other_post
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'can desassociate an object by setting it as nil' do
|
129
|
+
comment.post = nil
|
130
|
+
expect(comment.post_id).to eq nil
|
131
|
+
expect(comment.post).to eq nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when the SObject is namespaced' do
|
136
|
+
let(:attachment){ Foo::Attachment.new(id: '1', lead_id: '2') }
|
137
|
+
|
138
|
+
it 'generates the correct query' do
|
139
|
+
expect(client).to receive(:query).with("SELECT Id FROM Lead WHERE (Id = '2') LIMIT 1")
|
140
|
+
attachment.lead
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'instantiates the correct object' do
|
144
|
+
expect(attachment.lead).to be_instance_of(Foo::Lead)
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when given a foreign key' do
|
148
|
+
let(:attachment){ Foo::Attachment.new(id: '1', fancy_lead_id: '2') }
|
149
|
+
|
150
|
+
it 'generates the correct query' do
|
151
|
+
expect(client).to receive(:query).with("SELECT Id FROM Lead WHERE (Id = '2') LIMIT 1")
|
152
|
+
attachment.fancy_lead
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -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
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::SObject do
|
4
|
+
let(:client) { double 'Client', create!: 'id' }
|
5
|
+
|
6
|
+
before do
|
7
|
+
ActiveForce.sfdc_client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "save" do
|
11
|
+
it 'call action callback when save a record' do
|
12
|
+
whizbanged = Whizbang.new
|
13
|
+
whizbanged.save
|
14
|
+
expect(whizbanged.updated_from).to eq 'Rails'
|
15
|
+
expect(whizbanged.dirty_attribute).to eq true
|
16
|
+
expect(whizbanged.changed.include? 'dirty_attribute').to eq true
|
17
|
+
expect(whizbanged.changed.include? 'updated_from').to eq false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -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
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::Query do
|
4
|
+
let(:query) do
|
5
|
+
query = ActiveForce::Query.new 'table_name'
|
6
|
+
query.fields ['name', 'etc']
|
7
|
+
query
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.select' do
|
11
|
+
it 'use column sent on the select method' do
|
12
|
+
expect(query.select('name').all.to_s).to eq "SELECT name FROM table_name"
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'use columns sent on the select method' do
|
16
|
+
expect(query.select(['id','name']).all.to_s).to eq "SELECT id, name FROM table_name"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".all" do
|
21
|
+
it "table should return table name" do
|
22
|
+
expect(query.all.table).to eq(query.table)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "fields should return fields" do
|
26
|
+
expect(query.all.fields).to eq query.fields
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".all.to_s" do
|
31
|
+
it "should return a query for all records" do
|
32
|
+
expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should ignore dupicated attributes in select statment" do
|
36
|
+
query.fields ['Id', 'name', 'etc']
|
37
|
+
expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".where" do
|
42
|
+
it "should add a where condition to a query" do
|
43
|
+
expect(query.where("name like '%a%'").to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (name like '%a%')"
|
44
|
+
end
|
45
|
+
|
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)"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".limit" do
|
52
|
+
it "should add a limit to a query" do
|
53
|
+
expect(query.limit("25").to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe ".limit_value" do
|
58
|
+
it "should return the limit value" do
|
59
|
+
query.limit(4)
|
60
|
+
expect(query.limit_value).to eq 4
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ".offset" do
|
65
|
+
it "should add an offset to a query" do
|
66
|
+
expect(query.offset(4).to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".offset_value" do
|
71
|
+
it "should return the offset value" do
|
72
|
+
query.offset(4)
|
73
|
+
expect(query.offset_value).to eq 4
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe ".find.to_s" do
|
78
|
+
it "should return a query for 1 record" do
|
79
|
+
expect(query.find(2).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (Id = '2') LIMIT 1"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe ".order" do
|
84
|
+
it "should add a order condition in the statment" do
|
85
|
+
expect(query.order("name desc").to_s).to eq "SELECT Id, name, etc FROM table_name ORDER BY name desc"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should add a order condition in the statment with WHERE and LIMIT" do
|
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"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '.join' do
|
94
|
+
let(:join_query) do
|
95
|
+
join = ActiveForce::Query.new 'join_table_name'
|
96
|
+
join.fields ['name', 'etc']
|
97
|
+
join
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should add another select statment on the current select' do
|
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'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '.first' do
|
106
|
+
it 'should return the query for the first record' do
|
107
|
+
expect(query.first.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '.last' do
|
112
|
+
it 'should return the query for the last record' do
|
113
|
+
expect(query.last.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe ".count" do
|
118
|
+
it "should return the query for getting the row count" do
|
119
|
+
expect(query.count.to_s).to eq 'SELECT count(Id) FROM table_name'
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should work with a condition" do
|
123
|
+
expect(query.where("name = 'cool'").count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|