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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b2f8154faa82f569ece3b6f591dd527f4adb723
4
- data.tar.gz: daddd3d9d7601222b1afd816e42d45aa9b11453d
3
+ metadata.gz: 36ac23672709a2d24f9193d4d8cabbaf0bcb4e35
4
+ data.tar.gz: 8d9f0bbeab71f7a1edf1c6159887f63b27865708
5
5
  SHA512:
6
- metadata.gz: fbc8532491a16de2fb62c1ad1076a326f9eca24ae5e6bc7f18f44e157b0f4a7901887688c0afa405fe66211bf9093587ef555232f3612ca4e23907c0ec4920c6
7
- data.tar.gz: 921d7933ef5c198dd382e578b8e0176515f8587b05c29dbf8c53ad0a30c3be984c5b1b516e40e9a5a162066bb66f57c6217a24b0a71eacd3ed2b09fbdc07af3d
6
+ metadata.gz: ff1d1b1d71a0a506dbae3b3aa9990474c2e9800bef66987040d9df20b790bc2eb6720330cbf69fc71c1fd3ef2f321ae16f0607bacb1648920c5f7decd7c2a698
7
+ data.tar.gz: 0152fb60d9d3a91ff76943c7be5cf64f480c365b46cd768bfbb224b9ac2c4f965db913f51b9a850134e653440f7df2ec755c31108a32132160fa2b6690e5f311
@@ -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["username"]
39
- self.password = configurations["password"]
40
- self.security_token = configurations["security_token"]
41
- self.client_id = configurations["client_id"]
42
- self.client_secret = configurations["client_secret"]
43
- self.host = configurations["host"]
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
@@ -36,7 +36,12 @@ module Restforce
36
36
 
37
37
  self.collection ||= {}
38
38
 
39
- attr_reader :database_record_type, :salesforce_record_type, :associations
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 = {
@@ -8,6 +8,8 @@ module Restforce
8
8
  # models defined in the Restforce::DB::RecordTypes namespace.
9
9
  class Base
10
10
 
11
+ include Enumerable
12
+
11
13
  # Public: Initialize a new Restforce::DB::RecordTypes::Base.
12
14
  #
13
15
  # record_type - The name or class of the system record type.
@@ -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 <= #{options[:before].utc.iso8601}" if options[:before]),
57
- ("SystemModstamp > #{options[:after].utc.iso8601}" if options[:after]),
58
- ].compact.join(" and ")
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. Currently unused.
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(_options = {})
42
+ def run(options = {})
41
43
  run_time = Time.now
42
44
 
43
- @salesforce_record_type.each(after: last_run, before: run_time) do |record|
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: last_run, before: run_time) do |record|
52
+ @database_record_type.each(after: after, before: before) do |record|
47
53
  @salesforce_record_type.sync!(record)
48
54
  end
49
55
 
@@ -3,7 +3,7 @@ module Restforce
3
3
  # :nodoc:
4
4
  module DB
5
5
 
6
- VERSION = "0.3.4"
6
+ VERSION = "0.3.5"
7
7
 
8
8
  end
9
9
 
@@ -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
- before do
10
- configuration.load(secrets)
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
- it "loads the credentials from a passed hash" do
14
- expect(configuration.username).to_equal secrets["username"]
15
- expect(configuration.password).to_equal secrets["password"]
16
- expect(configuration.security_token).to_equal secrets["security_token"]
17
- expect(configuration.client_id).to_equal secrets["client_id"]
18
- expect(configuration.client_secret).to_equal secrets["client_secret"]
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
@@ -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
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-03-31 00:00:00.000000000 Z
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