restforce-db 0.3.4 → 0.3.5
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/lib/restforce/db/command.rb +3 -0
- data/lib/restforce/db/configuration.rb +21 -6
- data/lib/restforce/db/mapping.rb +10 -1
- data/lib/restforce/db/record_types/base.rb +2 -0
- data/lib/restforce/db/record_types/salesforce.rb +17 -11
- data/lib/restforce/db/synchronizer.rb +10 -4
- data/lib/restforce/db/version.rb +1 -1
- data/lib/restforce/db/worker.rb +3 -1
- data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_each/loops_through_the_existing_records_in_Salesforce.yml +158 -0
- data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_does_not_meet_the_conditions/does_not_find_the_record.yml +157 -0
- data/test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_meets_the_conditions/finds_the_record.yml +158 -0
- data/test/lib/restforce/db/configuration_test.rb +20 -9
- data/test/lib/restforce/db/record_types/salesforce_test.rb +33 -0
- data/test/support/utilities.rb +2 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36ac23672709a2d24f9193d4d8cabbaf0bcb4e35
|
4
|
+
data.tar.gz: 8d9f0bbeab71f7a1edf1c6159887f63b27865708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff1d1b1d71a0a506dbae3b3aa9990474c2e9800bef66987040d9df20b790bc2eb6720330cbf69fc71c1fd3ef2f321ae16f0607bacb1648920c5f7decd7c2a698
|
7
|
+
data.tar.gz: 0152fb60d9d3a91ff76943c7be5cf64f480c365b46cd768bfbb224b9ac2c4f965db913f51b9a850134e653440f7df2ec755c31108a32132160fa2b6690e5f311
|
data/lib/restforce/db/command.rb
CHANGED
@@ -83,6 +83,9 @@ module Restforce
|
|
83
83
|
opt.on("-c FILE", "--config FILE", "The location of a Restforce credentials file.") do |file|
|
84
84
|
@options[:config] = file
|
85
85
|
end
|
86
|
+
opt.on("-d N", "--delay N", "Amount of time by which to delay synchronization queries.") do |n|
|
87
|
+
@options[:delay] = n.to_f
|
88
|
+
end
|
86
89
|
opt.on("-i N", "--interval N", "Amount of time to wait between synchronizations.") do |n|
|
87
90
|
@options[:interval] = n.to_i
|
88
91
|
end
|
@@ -35,12 +35,27 @@ module Restforce
|
|
35
35
|
#
|
36
36
|
# Returns nothing.
|
37
37
|
def load(configurations)
|
38
|
-
self.username = configurations
|
39
|
-
self.password = configurations
|
40
|
-
self.security_token = configurations
|
41
|
-
self.client_id = configurations
|
42
|
-
self.client_secret = configurations
|
43
|
-
self.host = configurations
|
38
|
+
self.username = parsed(configurations, "username")
|
39
|
+
self.password = parsed(configurations, "password")
|
40
|
+
self.security_token = parsed(configurations, "security_token")
|
41
|
+
self.client_id = parsed(configurations, "client_id")
|
42
|
+
self.client_secret = parsed(configurations, "client_secret")
|
43
|
+
self.host = parsed(configurations, "host")
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Internal: Get the requested setting from a Hash of configurations.
|
49
|
+
#
|
50
|
+
# configurations - A Hash of configurations.
|
51
|
+
# setting - A String name of a single configuration in the Hash.
|
52
|
+
#
|
53
|
+
# Returns the value of the setting.
|
54
|
+
# Raises ArgumentError if the setting is not contained in the Hash.
|
55
|
+
def parsed(configurations, setting)
|
56
|
+
configurations.fetch setting do |key|
|
57
|
+
raise ArgumentError, "Configuration is missing #{key}"
|
58
|
+
end
|
44
59
|
end
|
45
60
|
|
46
61
|
end
|
data/lib/restforce/db/mapping.rb
CHANGED
@@ -36,7 +36,12 @@ module Restforce
|
|
36
36
|
|
37
37
|
self.collection ||= {}
|
38
38
|
|
39
|
-
attr_reader
|
39
|
+
attr_reader(
|
40
|
+
:database_record_type,
|
41
|
+
:salesforce_record_type,
|
42
|
+
:associations,
|
43
|
+
:conditions,
|
44
|
+
)
|
40
45
|
attr_writer :root
|
41
46
|
|
42
47
|
# Public: Initialize a new Restforce::DB::Mapping.
|
@@ -50,6 +55,9 @@ module Restforce
|
|
50
55
|
# :associations - A Hash of mappings between Active
|
51
56
|
# Record association names and the
|
52
57
|
# corresponding Salesforce Lookup name.
|
58
|
+
# :conditions - An Array of lookup conditions which
|
59
|
+
# should be applied to the Salesforce
|
60
|
+
# queries.
|
53
61
|
# :root - A Boolean reflecting whether or not
|
54
62
|
# this is a root-level mapping.
|
55
63
|
def initialize(database_model, salesforce_model, options = {})
|
@@ -58,6 +66,7 @@ module Restforce
|
|
58
66
|
|
59
67
|
@fields = options.fetch(:fields) { {} }
|
60
68
|
@associations = options.fetch(:associations) { {} }
|
69
|
+
@conditions = options.fetch(:conditions) { [] }
|
61
70
|
@root = options.fetch(:root) { false }
|
62
71
|
|
63
72
|
@types = {
|
@@ -31,10 +31,7 @@ module Restforce
|
|
31
31
|
#
|
32
32
|
# Returns nil or a Restforce::DB::Instances::Salesforce instance.
|
33
33
|
def find(id)
|
34
|
-
record = DB.client.query(
|
35
|
-
"select #{lookups} from #{@record_type} where Id = '#{id}'",
|
36
|
-
).first
|
37
|
-
|
34
|
+
record = DB.client.query(query("Id = '#{id}'")).first
|
38
35
|
return unless record
|
39
36
|
|
40
37
|
Instances::Salesforce.new(@record_type, record, @mapping)
|
@@ -53,14 +50,11 @@ module Restforce
|
|
53
50
|
# Returns nothing.
|
54
51
|
def each(options = {})
|
55
52
|
constraints = [
|
56
|
-
("SystemModstamp
|
57
|
-
("SystemModstamp
|
58
|
-
]
|
59
|
-
constraints = " where #{constraints}" unless constraints.empty?
|
60
|
-
|
61
|
-
query = "select #{lookups} from #{@record_type}#{constraints}"
|
53
|
+
("SystemModstamp < #{options[:before].utc.iso8601}" if options[:before]),
|
54
|
+
("SystemModstamp >= #{options[:after].utc.iso8601}" if options[:after]),
|
55
|
+
]
|
62
56
|
|
63
|
-
DB.client.query(query).each do |record|
|
57
|
+
DB.client.query(query(*constraints)).each do |record|
|
64
58
|
yield Instances::Salesforce.new(@record_type, record, @mapping)
|
65
59
|
end
|
66
60
|
end
|
@@ -86,6 +80,18 @@ module Restforce
|
|
86
80
|
record.synced?
|
87
81
|
end
|
88
82
|
|
83
|
+
# Internal: Get a query String, given an Array of existing conditions.
|
84
|
+
#
|
85
|
+
# conditions - An Array of conditions to append to the query.
|
86
|
+
#
|
87
|
+
# Returns a String.
|
88
|
+
def query(*conditions)
|
89
|
+
filters = (conditions + @mapping.conditions).compact.join(" and ")
|
90
|
+
filters = " where #{filters}" unless filters.empty?
|
91
|
+
|
92
|
+
"select #{lookups} from #{@record_type}#{filters}"
|
93
|
+
end
|
94
|
+
|
89
95
|
end
|
90
96
|
|
91
97
|
end
|
@@ -34,16 +34,22 @@ module Restforce
|
|
34
34
|
# overwriting recent changes to the database, in the event that Salesforce
|
35
35
|
# has also been updated since the last sync.
|
36
36
|
#
|
37
|
-
# options - A Hash of options for configuring the run.
|
37
|
+
# options - A Hash of options for configuring the run. Valid keys are:
|
38
|
+
# :delay - An offset to apply to the time filters. Allows the
|
39
|
+
# synchronization to account for server time drift.
|
38
40
|
#
|
39
41
|
# Returns the Time the run was performed.
|
40
|
-
def run(
|
42
|
+
def run(options = {})
|
41
43
|
run_time = Time.now
|
42
44
|
|
43
|
-
|
45
|
+
delay = options.fetch(:delay) { 0 }
|
46
|
+
before = run_time - delay
|
47
|
+
after = last_run - delay if last_run
|
48
|
+
|
49
|
+
@salesforce_record_type.each(after: after, before: before) do |record|
|
44
50
|
@database_record_type.sync!(record)
|
45
51
|
end
|
46
|
-
@database_record_type.each(after:
|
52
|
+
@database_record_type.each(after: after, before: before) do |record|
|
47
53
|
@salesforce_record_type.sync!(record)
|
48
54
|
end
|
49
55
|
|
data/lib/restforce/db/version.rb
CHANGED
data/lib/restforce/db/worker.rb
CHANGED
@@ -7,6 +7,7 @@ module Restforce
|
|
7
7
|
class Worker
|
8
8
|
|
9
9
|
DEFAULT_INTERVAL = 5
|
10
|
+
DEFAULT_DELAY = 1
|
10
11
|
|
11
12
|
class << self
|
12
13
|
|
@@ -51,6 +52,7 @@ module Restforce
|
|
51
52
|
def initialize(options = {})
|
52
53
|
@verbose = options.fetch(:verbose) { false }
|
53
54
|
@interval = options.fetch(:interval) { DEFAULT_INTERVAL }
|
55
|
+
@delay = options.fetch(:delay) { DEFAULT_DELAY }
|
54
56
|
|
55
57
|
Restforce::DB.reset
|
56
58
|
Restforce::DB.configure { |config| config.parse(options[:config]) }
|
@@ -136,7 +138,7 @@ module Restforce
|
|
136
138
|
# Returns a Boolean.
|
137
139
|
def synchronize(name, mapping)
|
138
140
|
log " SYNCHRONIZE #{name}"
|
139
|
-
runtime = Benchmark.realtime { mapping.synchronizer.run }
|
141
|
+
runtime = Benchmark.realtime { mapping.synchronizer.run(delay: @delay) }
|
140
142
|
log format(" COMPLETE after %.4f", runtime)
|
141
143
|
|
142
144
|
return true
|
@@ -0,0 +1,158 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://<host>/services/oauth2/token
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=password&client_id=<client_id>&client_secret=<client_secret>&username=<username>&password=<password><security_token>
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.1
|
12
|
+
Content-Type:
|
13
|
+
- application/x-www-form-urlencoded
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- "*/*"
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Wed, 01 Apr 2015 17:42:48 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=8KpISBKERgy2g417EyCKJg;Path=/;Domain=.salesforce.com;Expires=Sun,
|
27
|
+
31-May-2015 17:42:48 GMT
|
28
|
+
Expires:
|
29
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
30
|
+
Pragma:
|
31
|
+
- no-cache
|
32
|
+
Cache-Control:
|
33
|
+
- no-cache, no-store
|
34
|
+
Content-Type:
|
35
|
+
- application/json;charset=UTF-8
|
36
|
+
Transfer-Encoding:
|
37
|
+
- chunked
|
38
|
+
body:
|
39
|
+
encoding: ASCII-8BIT
|
40
|
+
string: '{"id":"https://login.salesforce.com/id/00D1a000000H3O9EAK/0051a000000UGT8AAO","issued_at":"1427910168476","token_type":"Bearer","instance_url":"https://<host>","signature":"NrGCnWPtuW3F1C8VyTV7HxO5FJosOMjVa/Mp89FnAAE=","access_token":"00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Wed, 01 Apr 2015 17:42:48 GMT
|
43
|
+
- request:
|
44
|
+
method: post
|
45
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"Name":"Sample object"}'
|
49
|
+
headers:
|
50
|
+
User-Agent:
|
51
|
+
- Faraday v0.9.1
|
52
|
+
Content-Type:
|
53
|
+
- application/json
|
54
|
+
Authorization:
|
55
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
56
|
+
Accept-Encoding:
|
57
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
58
|
+
Accept:
|
59
|
+
- "*/*"
|
60
|
+
response:
|
61
|
+
status:
|
62
|
+
code: 201
|
63
|
+
message: Created
|
64
|
+
headers:
|
65
|
+
Date:
|
66
|
+
- Wed, 01 Apr 2015 17:42:49 GMT
|
67
|
+
Set-Cookie:
|
68
|
+
- BrowserId=ZOjtoPSFTMiVnF96dDQ83w;Path=/;Domain=.salesforce.com;Expires=Sun,
|
69
|
+
31-May-2015 17:42:49 GMT
|
70
|
+
Expires:
|
71
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
72
|
+
Sforce-Limit-Info:
|
73
|
+
- api-usage=11/15000
|
74
|
+
Location:
|
75
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFfsAAG"
|
76
|
+
Content-Type:
|
77
|
+
- application/json;charset=UTF-8
|
78
|
+
Transfer-Encoding:
|
79
|
+
- chunked
|
80
|
+
body:
|
81
|
+
encoding: ASCII-8BIT
|
82
|
+
string: '{"id":"a001a000001LFfsAAG","success":true,"errors":[]}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Wed, 01 Apr 2015 17:42:49 GMT
|
85
|
+
- request:
|
86
|
+
method: get
|
87
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c
|
88
|
+
body:
|
89
|
+
encoding: US-ASCII
|
90
|
+
string: ''
|
91
|
+
headers:
|
92
|
+
User-Agent:
|
93
|
+
- Faraday v0.9.1
|
94
|
+
Authorization:
|
95
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
96
|
+
Accept-Encoding:
|
97
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
98
|
+
Accept:
|
99
|
+
- "*/*"
|
100
|
+
response:
|
101
|
+
status:
|
102
|
+
code: 200
|
103
|
+
message: OK
|
104
|
+
headers:
|
105
|
+
Date:
|
106
|
+
- Wed, 01 Apr 2015 17:42:50 GMT
|
107
|
+
Set-Cookie:
|
108
|
+
- BrowserId=9SFfcrRjRlqc6KnrgdGKyg;Path=/;Domain=.salesforce.com;Expires=Sun,
|
109
|
+
31-May-2015 17:42:50 GMT
|
110
|
+
Expires:
|
111
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
112
|
+
Sforce-Limit-Info:
|
113
|
+
- api-usage=11/15000
|
114
|
+
Content-Type:
|
115
|
+
- application/json;charset=UTF-8
|
116
|
+
Transfer-Encoding:
|
117
|
+
- chunked
|
118
|
+
body:
|
119
|
+
encoding: ASCII-8BIT
|
120
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFfsAAG"},"Id":"a001a000001LFfsAAG","SystemModstamp":"2015-04-01T17:42:49.000+0000","Name":"Sample
|
121
|
+
object","Example_Field__c":null}]}'
|
122
|
+
http_version:
|
123
|
+
recorded_at: Wed, 01 Apr 2015 17:42:50 GMT
|
124
|
+
- request:
|
125
|
+
method: delete
|
126
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFfsAAG
|
127
|
+
body:
|
128
|
+
encoding: US-ASCII
|
129
|
+
string: ''
|
130
|
+
headers:
|
131
|
+
User-Agent:
|
132
|
+
- Faraday v0.9.1
|
133
|
+
Authorization:
|
134
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
135
|
+
Accept-Encoding:
|
136
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
137
|
+
Accept:
|
138
|
+
- "*/*"
|
139
|
+
response:
|
140
|
+
status:
|
141
|
+
code: 204
|
142
|
+
message: No Content
|
143
|
+
headers:
|
144
|
+
Date:
|
145
|
+
- Wed, 01 Apr 2015 17:42:51 GMT
|
146
|
+
Set-Cookie:
|
147
|
+
- BrowserId=aX4v74VsTo2dEyXmodEWrw;Path=/;Domain=.salesforce.com;Expires=Sun,
|
148
|
+
31-May-2015 17:42:51 GMT
|
149
|
+
Expires:
|
150
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
151
|
+
Sforce-Limit-Info:
|
152
|
+
- api-usage=11/15000
|
153
|
+
body:
|
154
|
+
encoding: UTF-8
|
155
|
+
string: ''
|
156
|
+
http_version:
|
157
|
+
recorded_at: Wed, 01 Apr 2015 17:42:52 GMT
|
158
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,157 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://<host>/services/oauth2/token
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=password&client_id=<client_id>&client_secret=<client_secret>&username=<username>&password=<password><security_token>
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.1
|
12
|
+
Content-Type:
|
13
|
+
- application/x-www-form-urlencoded
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- "*/*"
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Wed, 01 Apr 2015 17:51:22 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=y9Xwyc7sRiS-SYlyinh-gg;Path=/;Domain=.salesforce.com;Expires=Sun,
|
27
|
+
31-May-2015 17:51:22 GMT
|
28
|
+
Expires:
|
29
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
30
|
+
Pragma:
|
31
|
+
- no-cache
|
32
|
+
Cache-Control:
|
33
|
+
- no-cache, no-store
|
34
|
+
Content-Type:
|
35
|
+
- application/json;charset=UTF-8
|
36
|
+
Transfer-Encoding:
|
37
|
+
- chunked
|
38
|
+
body:
|
39
|
+
encoding: ASCII-8BIT
|
40
|
+
string: '{"id":"https://login.salesforce.com/id/00D1a000000H3O9EAK/0051a000000UGT8AAO","issued_at":"1427910682943","token_type":"Bearer","instance_url":"https://<host>","signature":"XV2VCZfDmhSb6On2Br5cxsAz/NvNH3JlkOdbLX/clPY=","access_token":"00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Wed, 01 Apr 2015 17:51:23 GMT
|
43
|
+
- request:
|
44
|
+
method: post
|
45
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"Visible__c":false}'
|
49
|
+
headers:
|
50
|
+
User-Agent:
|
51
|
+
- Faraday v0.9.1
|
52
|
+
Content-Type:
|
53
|
+
- application/json
|
54
|
+
Authorization:
|
55
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
56
|
+
Accept-Encoding:
|
57
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
58
|
+
Accept:
|
59
|
+
- "*/*"
|
60
|
+
response:
|
61
|
+
status:
|
62
|
+
code: 201
|
63
|
+
message: Created
|
64
|
+
headers:
|
65
|
+
Date:
|
66
|
+
- Wed, 01 Apr 2015 17:51:23 GMT
|
67
|
+
Set-Cookie:
|
68
|
+
- BrowserId=Kfkv4LuQR3-iN46hIDKtug;Path=/;Domain=.salesforce.com;Expires=Sun,
|
69
|
+
31-May-2015 17:51:23 GMT
|
70
|
+
Expires:
|
71
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
72
|
+
Sforce-Limit-Info:
|
73
|
+
- api-usage=17/15000
|
74
|
+
Location:
|
75
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFgMAAW"
|
76
|
+
Content-Type:
|
77
|
+
- application/json;charset=UTF-8
|
78
|
+
Transfer-Encoding:
|
79
|
+
- chunked
|
80
|
+
body:
|
81
|
+
encoding: ASCII-8BIT
|
82
|
+
string: '{"id":"a001a000001LFgMAAW","success":true,"errors":[]}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Wed, 01 Apr 2015 17:51:24 GMT
|
85
|
+
- request:
|
86
|
+
method: get
|
87
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c%20where%20Id%20=%20%27a001a000001LFgMAAW%27%20and%20Visible__c%20=%20TRUE
|
88
|
+
body:
|
89
|
+
encoding: US-ASCII
|
90
|
+
string: ''
|
91
|
+
headers:
|
92
|
+
User-Agent:
|
93
|
+
- Faraday v0.9.1
|
94
|
+
Authorization:
|
95
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
96
|
+
Accept-Encoding:
|
97
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
98
|
+
Accept:
|
99
|
+
- "*/*"
|
100
|
+
response:
|
101
|
+
status:
|
102
|
+
code: 200
|
103
|
+
message: OK
|
104
|
+
headers:
|
105
|
+
Date:
|
106
|
+
- Wed, 01 Apr 2015 17:51:25 GMT
|
107
|
+
Set-Cookie:
|
108
|
+
- BrowserId=YzZvI_D3ShuJoLZb3ROxkQ;Path=/;Domain=.salesforce.com;Expires=Sun,
|
109
|
+
31-May-2015 17:51:25 GMT
|
110
|
+
Expires:
|
111
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
112
|
+
Sforce-Limit-Info:
|
113
|
+
- api-usage=17/15000
|
114
|
+
Content-Type:
|
115
|
+
- application/json;charset=UTF-8
|
116
|
+
Transfer-Encoding:
|
117
|
+
- chunked
|
118
|
+
body:
|
119
|
+
encoding: ASCII-8BIT
|
120
|
+
string: '{"totalSize":0,"done":true,"records":[]}'
|
121
|
+
http_version:
|
122
|
+
recorded_at: Wed, 01 Apr 2015 17:51:25 GMT
|
123
|
+
- request:
|
124
|
+
method: delete
|
125
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFgMAAW
|
126
|
+
body:
|
127
|
+
encoding: US-ASCII
|
128
|
+
string: ''
|
129
|
+
headers:
|
130
|
+
User-Agent:
|
131
|
+
- Faraday v0.9.1
|
132
|
+
Authorization:
|
133
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
134
|
+
Accept-Encoding:
|
135
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
136
|
+
Accept:
|
137
|
+
- "*/*"
|
138
|
+
response:
|
139
|
+
status:
|
140
|
+
code: 204
|
141
|
+
message: No Content
|
142
|
+
headers:
|
143
|
+
Date:
|
144
|
+
- Wed, 01 Apr 2015 17:51:26 GMT
|
145
|
+
Set-Cookie:
|
146
|
+
- BrowserId=KChk1bwkRkeQl0fwoxj5TQ;Path=/;Domain=.salesforce.com;Expires=Sun,
|
147
|
+
31-May-2015 17:51:26 GMT
|
148
|
+
Expires:
|
149
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
150
|
+
Sforce-Limit-Info:
|
151
|
+
- api-usage=17/15000
|
152
|
+
body:
|
153
|
+
encoding: UTF-8
|
154
|
+
string: ''
|
155
|
+
http_version:
|
156
|
+
recorded_at: Wed, 01 Apr 2015 17:51:26 GMT
|
157
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,158 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://<host>/services/oauth2/token
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=password&client_id=<client_id>&client_secret=<client_secret>&username=<username>&password=<password><security_token>
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.1
|
12
|
+
Content-Type:
|
13
|
+
- application/x-www-form-urlencoded
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- "*/*"
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Wed, 01 Apr 2015 17:51:18 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=-n50WpbhSAmLOfePSfw1JA;Path=/;Domain=.salesforce.com;Expires=Sun,
|
27
|
+
31-May-2015 17:51:18 GMT
|
28
|
+
Expires:
|
29
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
30
|
+
Pragma:
|
31
|
+
- no-cache
|
32
|
+
Cache-Control:
|
33
|
+
- no-cache, no-store
|
34
|
+
Content-Type:
|
35
|
+
- application/json;charset=UTF-8
|
36
|
+
Transfer-Encoding:
|
37
|
+
- chunked
|
38
|
+
body:
|
39
|
+
encoding: ASCII-8BIT
|
40
|
+
string: '{"id":"https://login.salesforce.com/id/00D1a000000H3O9EAK/0051a000000UGT8AAO","issued_at":"1427910678934","token_type":"Bearer","instance_url":"https://<host>","signature":"r7U6IsW9cCkVABj4E879KcDbgJZSkrit4swb8PBuwtw=","access_token":"00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Wed, 01 Apr 2015 17:51:19 GMT
|
43
|
+
- request:
|
44
|
+
method: post
|
45
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"Name":"Sample object"}'
|
49
|
+
headers:
|
50
|
+
User-Agent:
|
51
|
+
- Faraday v0.9.1
|
52
|
+
Content-Type:
|
53
|
+
- application/json
|
54
|
+
Authorization:
|
55
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
56
|
+
Accept-Encoding:
|
57
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
58
|
+
Accept:
|
59
|
+
- "*/*"
|
60
|
+
response:
|
61
|
+
status:
|
62
|
+
code: 201
|
63
|
+
message: Created
|
64
|
+
headers:
|
65
|
+
Date:
|
66
|
+
- Wed, 01 Apr 2015 17:51:19 GMT
|
67
|
+
Set-Cookie:
|
68
|
+
- BrowserId=uBlo3fFFSeOgxVD78aQnJg;Path=/;Domain=.salesforce.com;Expires=Sun,
|
69
|
+
31-May-2015 17:51:19 GMT
|
70
|
+
Expires:
|
71
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
72
|
+
Sforce-Limit-Info:
|
73
|
+
- api-usage=17/15000
|
74
|
+
Location:
|
75
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFgHAAW"
|
76
|
+
Content-Type:
|
77
|
+
- application/json;charset=UTF-8
|
78
|
+
Transfer-Encoding:
|
79
|
+
- chunked
|
80
|
+
body:
|
81
|
+
encoding: ASCII-8BIT
|
82
|
+
string: '{"id":"a001a000001LFgHAAW","success":true,"errors":[]}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Wed, 01 Apr 2015 17:51:20 GMT
|
85
|
+
- request:
|
86
|
+
method: get
|
87
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c%20where%20Id%20=%20%27a001a000001LFgHAAW%27%20and%20Visible__c%20=%20TRUE
|
88
|
+
body:
|
89
|
+
encoding: US-ASCII
|
90
|
+
string: ''
|
91
|
+
headers:
|
92
|
+
User-Agent:
|
93
|
+
- Faraday v0.9.1
|
94
|
+
Authorization:
|
95
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
96
|
+
Accept-Encoding:
|
97
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
98
|
+
Accept:
|
99
|
+
- "*/*"
|
100
|
+
response:
|
101
|
+
status:
|
102
|
+
code: 200
|
103
|
+
message: OK
|
104
|
+
headers:
|
105
|
+
Date:
|
106
|
+
- Wed, 01 Apr 2015 17:51:20 GMT
|
107
|
+
Set-Cookie:
|
108
|
+
- BrowserId=0luURef9R7uia6N7fuHh9w;Path=/;Domain=.salesforce.com;Expires=Sun,
|
109
|
+
31-May-2015 17:51:20 GMT
|
110
|
+
Expires:
|
111
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
112
|
+
Sforce-Limit-Info:
|
113
|
+
- api-usage=18/15000
|
114
|
+
Content-Type:
|
115
|
+
- application/json;charset=UTF-8
|
116
|
+
Transfer-Encoding:
|
117
|
+
- chunked
|
118
|
+
body:
|
119
|
+
encoding: ASCII-8BIT
|
120
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFgHAAW"},"Id":"a001a000001LFgHAAW","SystemModstamp":"2015-04-01T17:51:19.000+0000","Name":"Sample
|
121
|
+
object","Example_Field__c":null}]}'
|
122
|
+
http_version:
|
123
|
+
recorded_at: Wed, 01 Apr 2015 17:51:21 GMT
|
124
|
+
- request:
|
125
|
+
method: delete
|
126
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001LFgHAAW
|
127
|
+
body:
|
128
|
+
encoding: US-ASCII
|
129
|
+
string: ''
|
130
|
+
headers:
|
131
|
+
User-Agent:
|
132
|
+
- Faraday v0.9.1
|
133
|
+
Authorization:
|
134
|
+
- OAuth 00D1a000000H3O9!AQ4AQKZwdgw8XRPQOd9_ipgseq9yxNqcklYDcsxnqhIM56FN53.IU986f9x29rxVXv5E_w_ReuA_8Q2P_TTVjLPBPmxzVeiW
|
135
|
+
Accept-Encoding:
|
136
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
137
|
+
Accept:
|
138
|
+
- "*/*"
|
139
|
+
response:
|
140
|
+
status:
|
141
|
+
code: 204
|
142
|
+
message: No Content
|
143
|
+
headers:
|
144
|
+
Date:
|
145
|
+
- Wed, 01 Apr 2015 17:51:21 GMT
|
146
|
+
Set-Cookie:
|
147
|
+
- BrowserId=WdYv53V1RZqLRR4JQ5mc5A;Path=/;Domain=.salesforce.com;Expires=Sun,
|
148
|
+
31-May-2015 17:51:21 GMT
|
149
|
+
Expires:
|
150
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
151
|
+
Sforce-Limit-Info:
|
152
|
+
- api-usage=17/15000
|
153
|
+
body:
|
154
|
+
encoding: UTF-8
|
155
|
+
string: ''
|
156
|
+
http_version:
|
157
|
+
recorded_at: Wed, 01 Apr 2015 17:51:22 GMT
|
158
|
+
recorded_with: VCR 2.9.3
|
@@ -6,17 +6,28 @@ describe Restforce::DB::Configuration do
|
|
6
6
|
let(:configuration) { Restforce::DB::Configuration.new }
|
7
7
|
|
8
8
|
describe "#load" do
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
describe "when all configurations are supplied" do
|
11
|
+
before do
|
12
|
+
configuration.load(secrets)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "loads the credentials from a passed hash" do
|
16
|
+
expect(configuration.username).to_equal secrets["username"]
|
17
|
+
expect(configuration.password).to_equal secrets["password"]
|
18
|
+
expect(configuration.security_token).to_equal secrets["security_token"]
|
19
|
+
expect(configuration.client_id).to_equal secrets["client_id"]
|
20
|
+
expect(configuration.client_secret).to_equal secrets["client_secret"]
|
21
|
+
expect(configuration.host).to_equal secrets["host"]
|
22
|
+
end
|
11
23
|
end
|
12
24
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
expect(configuration.host).to_equal secrets["host"]
|
25
|
+
describe "when the loaded configuration is missing one or more keys" do
|
26
|
+
let(:secrets) { {} }
|
27
|
+
|
28
|
+
it "raises an error" do
|
29
|
+
expect(-> { configuration.load(secrets) }).to_raise(ArgumentError)
|
30
|
+
end
|
20
31
|
end
|
21
32
|
end
|
22
33
|
|
@@ -41,5 +41,38 @@ describe Restforce::DB::RecordTypes::Salesforce do
|
|
41
41
|
it "returns nil when no matching record exists" do
|
42
42
|
expect(record_type.find("a001a000001E1vFAKE")).to_be_nil
|
43
43
|
end
|
44
|
+
|
45
|
+
describe "given a set of mapping conditions" do
|
46
|
+
let(:conditions) { ["Visible__c = TRUE"] }
|
47
|
+
|
48
|
+
describe "when a record meets the conditions" do
|
49
|
+
|
50
|
+
it "finds the record" do
|
51
|
+
expect(record_type.find(id)).to_be_instance_of Restforce::DB::Instances::Salesforce
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when a record does not meet the conditions" do
|
56
|
+
let(:id) { Salesforce.create!(salesforce_model, "Visible__c" => false) }
|
57
|
+
|
58
|
+
it "does not find the record" do
|
59
|
+
expect(record_type.find(id)).to_be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
44
63
|
end
|
64
|
+
|
65
|
+
describe "#each", :vcr do
|
66
|
+
let(:id) { Salesforce.create!(salesforce_model) }
|
67
|
+
before { id }
|
68
|
+
|
69
|
+
# Restforce::DB::RecordType::Salesforce actually implements Enumerable, so
|
70
|
+
# we're just going with a trivially testable portion of the Enumerable API.
|
71
|
+
it "loops through the existing records in Salesforce" do
|
72
|
+
record = record_type.first
|
73
|
+
expect(record).to_be_instance_of(Restforce::DB::Instances::Salesforce)
|
74
|
+
expect(record.id).to_equal(id)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
45
78
|
end
|
data/test/support/utilities.rb
CHANGED
@@ -17,6 +17,7 @@ def mappings!
|
|
17
17
|
let(:salesforce_model) { "CustomObject__c" }
|
18
18
|
let(:fields) { { name: "Name", example: "Example_Field__c" } }
|
19
19
|
let(:associations) { {} }
|
20
|
+
let(:conditions) { [] }
|
20
21
|
let!(:mapping) do
|
21
22
|
Restforce::DB::Mapping.new(
|
22
23
|
database_model,
|
@@ -24,6 +25,7 @@ def mappings!
|
|
24
25
|
root: true,
|
25
26
|
fields: fields,
|
26
27
|
associations: associations,
|
28
|
+
conditions: conditions,
|
27
29
|
)
|
28
30
|
end
|
29
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restforce-db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Horner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -242,7 +242,10 @@ files:
|
|
242
242
|
- test/cassettes/Restforce_DB_Instances_Salesforce/_update_/updates_the_record_in_Salesforce_with_the_passed_attributes.yml
|
243
243
|
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/creates_a_record_in_Salesforce_from_the_passed_database_record_s_attributes.yml
|
244
244
|
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_create_/updates_the_database_record_with_the_Salesforce_record_s_ID.yml
|
245
|
+
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_each/loops_through_the_existing_records_in_Salesforce.yml
|
245
246
|
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/finds_existing_records_in_Salesforce.yml
|
247
|
+
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_does_not_meet_the_conditions/does_not_find_the_record.yml
|
248
|
+
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/given_a_set_of_mapping_conditions/when_a_record_meets_the_conditions/finds_the_record.yml
|
246
249
|
- test/cassettes/Restforce_DB_RecordTypes_Salesforce/_find/returns_nil_when_no_matching_record_exists.yml
|
247
250
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_synchronization_is_stale/updates_the_database_record.yml
|
248
251
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/when_synchronization_is_up-to-date/does_not_update_the_database_record.yml
|