rforce 0.11 → 0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f5d3cfdef0e31e56d1bc1d770e79f26323d0a6c
4
+ data.tar.gz: a73f9b20c24d37ba4a3a68b2c43e16a1d9204822
5
+ SHA512:
6
+ metadata.gz: 861c42017d1f723532b074fef3e400e843f1fcf20e4da5448add773a769c02dc2c6ce17f2fc24d7eb009a44015e944f5297d8c55b8306dcbb71dc076b9004359
7
+ data.tar.gz: baa7d21e2f81675213086da031bb0eca550658d3a9625f94f9a7e820fa4c51bc4a620804356fa8f00dd8688c6537b7d4fa4133a47ad8ee9f8d7c156e26a4e2d3
@@ -1,3 +1,12 @@
1
+ == 0.12.0 2014-07-27
2
+ * 2 enhancements
3
+ * Clearer errors when skipping login (Victor Stan)
4
+ * Allow passing in an optional logger (Jeff Jolma)
5
+ * 3 bug fixes
6
+ * Fixed URL error in OAuth flow (reported by karthickbabuos)
7
+ * Corrected UTF-8 handling error (Maxime Rety)
8
+ * Fixed repeat login issue (Jeff Jolma)
9
+
1
10
  == 0.11.0 2013-06-08
2
11
  * 1 minor enhancement
3
12
  * Give the README an .rdoc extension for easy Github viewing
@@ -2,13 +2,15 @@ History.txt
2
2
  Manifest.txt
3
3
  README.rdoc
4
4
  Rakefile
5
+ examples/oauth_setup.rb
6
+ examples/oauth_use.rb
7
+ examples/simple.rb
5
8
  lib/rforce.rb
6
9
  lib/rforce/binding.rb
7
10
  lib/rforce/method_keys.rb
8
11
  lib/rforce/soap_pullable.rb
9
12
  lib/rforce/soap_response.rb
10
13
  lib/rforce/soap_response_expat.rb
11
- lib/rforce/soap_response_hpricot.rb
12
14
  lib/rforce/soap_response_nokogiri.rb
13
15
  lib/rforce/soap_response_rexml.rb
14
16
  lib/rforce/version.rb
@@ -1,9 +1,8 @@
1
1
  = rforce
2
2
 
3
- * http://rforce.rubyforge.org
4
- * http://rubyforge.org/projects/rforce
5
- * http://bitbucket.org/undees/rforce
6
3
  * http://github.com/undees/rforce
4
+ * http://bitbucket.org/undees/rforce
5
+ * http://rdoc.info/github/undees/rforce
7
6
 
8
7
  == DESCRIPTION:
9
8
 
@@ -75,7 +74,7 @@ Rather than enforcing adherence to the sforce.com schema, RForce assumes you are
75
74
 
76
75
  == LICENSE:
77
76
 
78
- Copyright (c) 2005-2013 Ian Dees and contributors
77
+ Copyright (c) 2005-2014 Ian Dees and contributors
79
78
 
80
79
  Permission is hereby granted, free of charge, to any person obtaining
81
80
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -8,16 +8,19 @@ require 'hoe/gemspec2'
8
8
  Hoe.plugin :gemspec2
9
9
 
10
10
  Hoe.spec 'rforce' do
11
+ is_jruby = (RUBY_PLATFORM == 'java')
12
+ is_ruby18 = (RUBY_VERSION =~ /^1.8/)
13
+
11
14
  developer('Ian Dees', 'undees@gmail.com')
15
+ license('MIT')
12
16
 
13
17
  self.extra_deps << ['builder', '~> 3.0']
14
18
  self.extra_deps << ['oauth', '~> 0.4']
15
19
 
16
20
  self.extra_dev_deps << ['rspec', '~> 2.8']
17
21
  self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
18
- self.extra_dev_deps << ['hpricot', '~> 0.8']
19
- self.extra_dev_deps << ['nokogiri', '~> 1.5']
20
- self.extra_dev_deps << ['xmlparser', '~> 0.7']
22
+ self.extra_dev_deps << ['nokogiri', '~> 1.5'] unless is_ruby18
23
+ self.extra_dev_deps << ['xmlparser', '~> 0.7'] unless is_jruby
21
24
 
22
25
  self.rdoc_locations = ['undees@rforce.rubyforge.org:/var/www/gforge-projects/rforce']
23
26
  self.remote_rdoc_dir = ''
@@ -0,0 +1,26 @@
1
+ require 'oauth'
2
+
3
+ consumer_key = ENV['SALESFORCE_CONSUMER_KEY']
4
+ consumer_secret = ENV['SALESFORCE_CONSUMER_SECRET']
5
+
6
+ oauth_options = {
7
+ :site => 'https://login.salesforce.com',
8
+ :scheme => :body,
9
+ :request_token_path => '/_nc_external/system/security/oauth/RequestTokenHandler',
10
+ :authorize_path => '/setup/secur/RemoteAccessAuthorizationPage.apexp',
11
+ :access_token_path => '/_nc_external/system/security/oauth/AccessTokenHandler',
12
+ }
13
+
14
+ consumer = OAuth::Consumer.new consumer_key, consumer_secret, oauth_options
15
+ # consumer.http.set_debug_output STDERR # if you're curious
16
+
17
+ request = consumer.get_request_token
18
+ authorize_url = request.authorize_url :oauth_consumer_key => consumer_key
19
+
20
+ puts "Go to #{authorize_url} in your browser, then enter the verification code:"
21
+ verification_code = gets.strip
22
+
23
+ access = request.get_access_token :oauth_verifier => verification_code
24
+
25
+ puts "Access Token: " + access.token
26
+ puts "Access Secret: " + access.secret
@@ -0,0 +1,25 @@
1
+ require 'rforce'
2
+
3
+ oauth = {
4
+ :consumer_key => ENV['SALESFORCE_CONSUMER_KEY'],
5
+ :consumer_secret => ENV['SALESFORCE_CONSUMER_SECRET'],
6
+ :access_token => ENV['SALESFORCE_ACCESS_TOKEN'],
7
+ :access_secret => ENV['SALESFORCE_ACCESS_SECRET'],
8
+ :login_url => 'https://login.salesforce.com/services/OAuth/u/20.0'
9
+ }
10
+
11
+ binding = RForce::Binding.new \
12
+ 'https://www.salesforce.com/services/Soap/u/20.0',
13
+ nil,
14
+ oauth
15
+
16
+ binding.login_with_oauth
17
+
18
+ answer = binding.search \
19
+ :searchString =>
20
+ 'find {McFakerson Co} in name fields returning account(id)'
21
+
22
+ account = answer.searchResponse.result.searchRecords.record
23
+ account_id = account.Id
24
+
25
+ puts account_id
@@ -0,0 +1,20 @@
1
+ require 'rforce'
2
+
3
+ email = ENV['SALESFORCE_USER']
4
+ password = ENV['SALESFORCE_PASS']
5
+ token = ENV['SALESFORCE_TOKEN']
6
+
7
+ binding = RForce::Binding.new \
8
+ 'https://www.salesforce.com/services/Soap/u/20.0'
9
+
10
+ binding.login \
11
+ email, password + token
12
+
13
+ answer = binding.search \
14
+ :searchString =>
15
+ 'find {McFakerson Co} in name fields returning account(id)'
16
+
17
+ account = answer.searchResponse.result.searchRecords.record
18
+ account_id = account.Id
19
+
20
+ puts account_id
@@ -44,99 +44,87 @@ module RForce
44
44
  MruHeader = '<partner:MruHeader soap:mustUnderstand="1"><partner:updateMru>true</partner:updateMru></partner:MruHeader>'
45
45
  ClientIdHeader = '<partner:CallOptions soap:mustUnderstand="1"><partner:client>%s</partner:client></partner:CallOptions>'
46
46
 
47
- # Connect to the server securely. If you pass an oauth hash, it
48
- # must contain the keys :consumer_key, :consumer_secret,
47
+ # Create a binding to the server (after which you can call login
48
+ # or login_with_oauth to connect to it). If you pass an oauth
49
+ # hash, it must contain the keys :consumer_key, :consumer_secret,
49
50
  # :access_token, :access_secret, and :login_url.
50
51
  #
51
52
  # proxy may be a URL of the form http://user:pass@example.com:port
52
53
  #
53
- def initialize(url, sid = nil, oauth = nil, proxy = nil)
54
+ # if a logger is specified, it will be used for very verbose SOAP logging
55
+ #
56
+ def initialize(url, sid = nil, oauth = nil, proxy = nil, logger = nil)
54
57
  @session_id = sid
55
58
  @oauth = oauth
56
59
  @proxy = proxy
57
60
  @batch_size = DEFAULT_BATCH_SIZE
58
-
59
- init_server(url)
61
+ @logger = logger
62
+ @url = URI.parse(url)
60
63
  end
61
64
 
62
-
63
65
  def show_debug
64
66
  ENV['SHOWSOAP'] == 'true'
65
67
  end
66
68
 
69
+ def create_server(url)
70
+ server = Net::HTTP.Proxy(@proxy).new(url.host, url.port)
71
+ server.use_ssl = (url.scheme == 'https')
72
+ server.verify_mode = OpenSSL::SSL::VERIFY_NONE
67
73
 
68
- def init_server(url)
69
- @url = URI.parse(url)
70
-
71
- if (@oauth)
72
- consumer = OAuth::Consumer.new \
73
- @oauth[:consumer_key],
74
- @oauth[:consumer_secret],
75
- {
76
- :site => url,
77
- :proxy => @proxy
78
- }
79
-
80
- consumer.http.set_debug_output $stderr if show_debug
81
-
82
- @server = OAuth::AccessToken.new \
83
- consumer,
84
- @oauth[:access_token],
85
- @oauth[:access_secret]
86
-
87
- class << @server
88
- alias_method :post2, :post
89
- end
90
- else
91
- @server = Net::HTTP.Proxy(@proxy).new(@url.host, @url.port)
92
- @server.use_ssl = @url.scheme == 'https'
93
- @server.verify_mode = OpenSSL::SSL::VERIFY_NONE
94
-
95
- # run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
96
- @server.set_debug_output $stderr if show_debug
97
- end
98
- end
99
-
100
- # Connect to remote server
101
- #
102
- def connect(user, password)
103
- @user = user
104
- @password = password
74
+ # run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
75
+ server.set_debug_output $stderr if show_debug
105
76
 
106
- call_remote(:login, [:username, user, :password, password])
77
+ return server
107
78
  end
108
79
 
109
80
  # Log in to the server with a user name and password, remembering
110
81
  # the session ID returned to us by Salesforce.
111
82
  def login(user, password)
112
- response = connect(user, password)
83
+ @user = user
84
+ @password = password
85
+ @server = create_server(@url)
86
+ response = call_remote(:login, [:username, user, :password, password])
113
87
 
114
88
  raise "Incorrect user name / password [#{response.Fault}]" unless response.loginResponse
115
89
 
116
- result = response[:loginResponse][:result]
90
+ result = response[:loginResponse][:result]
117
91
  @session_id = result[:sessionId]
92
+ @url = URI.parse(result[:serverUrl])
93
+ @server = create_server(@url)
118
94
 
119
- init_server(result[:serverUrl])
120
-
121
- response
95
+ return response
122
96
  end
123
97
 
124
98
  # Log in to the server with OAuth, remembering
125
99
  # the session ID returned to us by Salesforce.
126
100
  def login_with_oauth
127
- result = @server.post \
128
- @oauth[:login_url],
101
+ consumer = OAuth::Consumer.new \
102
+ @oauth[:consumer_key],
103
+ @oauth[:consumer_secret]
104
+
105
+ access = OAuth::AccessToken.new \
106
+ consumer, @oauth[:access_token],
107
+ @oauth[:access_secret]
108
+
109
+ login_url = @oauth[:login_url]
110
+
111
+ result = access.post \
112
+ login_url,
129
113
  '',
130
114
  {'content-type' => 'application/x-www-form-urlencoded'}
131
115
 
132
116
  case result
133
117
  when Net::HTTPSuccess
134
- doc = REXML::Document.new result.body
118
+ doc = REXML::Document.new result.body
135
119
  @session_id = doc.elements['*/sessionId'].text
136
- server_url = doc.elements['*/serverUrl'].text
137
- init_server server_url
120
+ @url = URI.parse(doc.elements['*/serverUrl'].text)
121
+ @server = access
122
+
123
+ class << @server
124
+ alias_method :post2, :post
125
+ end
138
126
 
139
- return {:sessionId => @sessionId, :serverUrl => server_url}
127
+ return {:sessionId => @session_id, :serverUrl => @url.to_s}
140
128
  when Net::HTTPUnauthorized
141
129
  raise 'Invalid OAuth tokens'
142
130
  else
@@ -148,8 +136,11 @@ module RForce
148
136
  # a hash or (if order is important) an array of alternating
149
137
  # keys and values.
150
138
  def call_remote(method, args)
139
+ # Different URI requirements for regular vs. OAuth. This is
140
+ # *screaming* for a refactor.
141
+ fallback_soap_url = @oauth ? @url.to_s : @url.path
151
142
 
152
- urn, soap_url = block_given? ? yield : ["urn:partner.soap.sforce.com", @url.path]
143
+ urn, soap_url = block_given? ? yield : ["urn:partner.soap.sforce.com", fallback_soap_url]
153
144
 
154
145
  # Create XML text from the arguments.
155
146
  expanded = ''
@@ -181,6 +172,7 @@ module RForce
181
172
  # Fill in the blanks of the SOAP envelope with our
182
173
  # session ID and the expanded XML of our request.
183
174
  request = (Envelope % [@session_id, extra_headers, expanded])
175
+ @logger && @logger.info("RForce request: #{request}")
184
176
 
185
177
  # reset the batch size for the next request
186
178
  @batch_size = DEFAULT_BATCH_SIZE
@@ -201,14 +193,23 @@ module RForce
201
193
  end
202
194
 
203
195
  # Send the request to the server and read the response.
196
+ @logger && @logger.info("RForce request to host #{@server} url #{soap_url} headers: #{headers}")
204
197
  response = @server.post2(soap_url, request.lstrip, headers)
205
198
 
206
199
  # decode if we have encoding
207
200
  content = decode(response)
208
201
 
202
+ # Fix charset encoding. Needed because the "content" variable may contain a UTF-8
203
+ # or ISO-8859-1 string, but is carrying the US-ASCII encoding.
204
+ content = fix_encoding(content)
205
+
209
206
  # Check to see if INVALID_SESSION_ID was raised and try to relogin in
210
207
  if method != :login and @session_id and content =~ /sf:INVALID_SESSION_ID/
211
- login(@user, @password)
208
+ if @user
209
+ login(@user, @password)
210
+ else
211
+ raise "INVALID_SESSION_ID"
212
+ end
212
213
 
213
214
  # repackage and rencode request with the new session id
214
215
  request = (Envelope % [@session_id, extra_headers, expanded])
@@ -218,12 +219,16 @@ module RForce
218
219
  response = @server.post2(soap_url, request.lstrip, headers)
219
220
 
220
221
  content = decode(response)
222
+
223
+ # Fix charset encoding. Needed because the "content" variable may contain a UTF-8
224
+ # or ISO-8859-1 string, but is carrying the US-ASCII encoding.
225
+ content = fix_encoding(content)
221
226
  end
222
227
 
228
+ @logger && @logger.info("RForce response: #{content}")
223
229
  SoapResponse.new(content).parse
224
230
  end
225
231
 
226
-
227
232
  # decode gzip
228
233
  def decode(response)
229
234
  encoding = response['Content-Encoding']
@@ -246,7 +251,6 @@ module RForce
246
251
  end
247
252
  end
248
253
 
249
-
250
254
  # encode gzip
251
255
  def encode(request)
252
256
  return request if show_debug
@@ -261,6 +265,28 @@ module RForce
261
265
  end
262
266
  end
263
267
 
268
+ # fix invalid US-ASCII strings by applying the correct encoding on ruby 1.9+
269
+ def fix_encoding(string)
270
+ if [:valid_encoding?, :force_encoding].all? { |m| string.respond_to?(m) }
271
+ if !string.valid_encoding?
272
+ # The 2 possible encodings in responses are UTF-8 and ISO-8859-1
273
+ # http://www.salesforce.com/us/developer/docs/api/Content/implementation_considerations.htm#topic-title_international
274
+ #
275
+ ["UTF-8", "ISO-8859-1"].each do |encoding_name|
276
+
277
+ s = string.dup.force_encoding(encoding_name)
278
+
279
+ if s.valid_encoding?
280
+ return s
281
+ end
282
+ end
283
+
284
+ raise "Invalid encoding in SOAP response: not in [US-ASCII, UTF-8, ISO-8859-1]"
285
+ end
286
+ end
287
+
288
+ return string
289
+ end
264
290
 
265
291
  # Turns method calls on this object into remote SOAP calls.
266
292
  def method_missing(method, *args)
@@ -1,5 +1,4 @@
1
1
  begin; require 'rforce/soap_response_nokogiri'; rescue LoadError; end
2
- begin; require 'rforce/soap_response_hpricot'; rescue LoadError; end
3
2
  begin; require 'rforce/soap_response_expat'; rescue LoadError; end
4
3
  require 'rforce/soap_response_rexml'
5
4
 
@@ -7,8 +6,7 @@ require 'rforce/soap_response_rexml'
7
6
  module RForce
8
7
  # Use the fastest XML parser available.
9
8
  SoapResponse =
10
- (RForce::const_get(:SoapResponseExpat) rescue nil) ||
11
9
  (RForce::const_get(:SoapResponseNokogiri) rescue nil) ||
12
- (RForce::const_get(:SoapResponseHpricot) rescue nil) ||
10
+ (RForce::const_get(:SoapResponseExpat) rescue nil) ||
13
11
  SoapResponseRexml
14
12
  end
@@ -1,3 +1,3 @@
1
1
  module RForce
2
- VERSION = '0.11'
2
+ VERSION = '0.12'
3
3
  end
@@ -60,7 +60,7 @@ describe 'a SoapResponse implementation' do
60
60
  fname = File.join(File.dirname(__FILE__), 'soap-response.xml')
61
61
  @contents = File.open(fname) {|f| f.read}
62
62
 
63
- [:rexml, :expat, :hpricot, :nokogiri].each do |processor|
63
+ [:rexml, :expat, :nokogiri].each do |processor|
64
64
  name = "SoapResponse#{processor.to_s.capitalize}".to_sym
65
65
  variable = "@#{processor}_recs".to_sym
66
66
 
@@ -82,14 +82,10 @@ describe 'a SoapResponse implementation' do
82
82
 
83
83
  # Special-case expat tests for CI
84
84
  it 'returns the same results with expat' do
85
- pending 'expat not installed' unless @expat_recs
85
+ skip 'expat not installed' unless @expat_recs
86
86
  @expat_recs.should == @rexml_recs
87
87
  end
88
88
 
89
- it 'returns the same results with hpricot' do
90
- @hpricot_recs.should == @rexml_recs
91
- end
92
-
93
89
  it 'understands XML entities' do
94
90
  expected = "Bee's knees"
95
91
  @rexml_recs.first.Description.should == expected
@@ -98,16 +94,6 @@ describe 'a SoapResponse implementation' do
98
94
  if @expat_recs
99
95
  @expat_recs.first.Description.should == expected
100
96
  end
101
-
102
- @hpricot_recs.first.Description.should == expected
103
- end
104
- end
105
-
106
- describe 'SoapResponseHpricot' do
107
- it 'parses basic XML entities' do
108
- text = '&lt;tag attr=&quot;Bee&apos;s knees &amp; toes&quot;&gt;'
109
- SoapResponseHpricot.unescapeXML(text).should ==
110
- %q(<tag attr="Bee's knees & toes">)
111
97
  end
112
98
  end
113
99
 
@@ -213,9 +199,11 @@ shared_examples_for 'a SOAP response' do
213
199
  end
214
200
  end
215
201
 
216
- describe 'SoapResponseNokogiri' do
217
- it_behaves_like 'a SOAP response' do
218
- let(:klass) { SoapResponseNokogiri }
202
+ if RForce.const_defined? :SoapResponseNokogiri
203
+ describe 'SoapResponseNokogiri' do
204
+ it_behaves_like 'a SOAP response' do
205
+ let(:klass) { SoapResponseNokogiri }
206
+ end
219
207
  end
220
208
  end
221
209
 
@@ -234,12 +222,6 @@ describe 'SoapResponseRexml' do
234
222
  end
235
223
  end
236
224
 
237
- describe 'SoapResponseHpricot' do
238
- it_behaves_like 'a SOAP response' do
239
- let(:klass) { SoapResponseHpricot }
240
- end
241
- end
242
-
243
225
  CreateXml = <<HERE.gsub(/\n\s*/, '')
244
226
  <partner:create>
245
227
  <partner:sObjects>
@@ -7,7 +7,6 @@ task :timing do
7
7
 
8
8
  [:SoapResponseRexml,
9
9
  :SoapResponseExpat,
10
- :SoapResponseHpricot,
11
10
  :SoapResponseNokogiri].each do |name|
12
11
  begin
13
12
  klass = RForce.const_get name
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rforce
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.11'
5
- prerelease:
4
+ version: '0.12'
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ian Dees
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-08 00:00:00.000000000 Z
11
+ date: 2014-07-28 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: builder
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: oauth
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,63 +34,55 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0.4'
46
41
  - !ruby/object:Gem::Dependency
47
- name: rspec
42
+ name: rdoc
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
53
- version: '2.8'
47
+ version: '4.0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
61
- version: '2.8'
54
+ version: '4.0'
62
55
  - !ruby/object:Gem::Dependency
63
- name: hoe-gemspec2
56
+ name: rspec
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
69
- version: '1.1'
61
+ version: '2.8'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
77
- version: '1.1'
68
+ version: '2.8'
78
69
  - !ruby/object:Gem::Dependency
79
- name: hpricot
70
+ name: hoe-gemspec2
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
85
- version: '0.8'
75
+ version: '1.1'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
93
- version: '0.8'
82
+ version: '1.1'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: nokogiri
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ~>
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ~>
108
95
  - !ruby/object:Gem::Version
@@ -110,7 +97,6 @@ dependencies:
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: xmlparser
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ~>
116
102
  - !ruby/object:Gem::Version
@@ -118,47 +104,28 @@ dependencies:
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ~>
124
109
  - !ruby/object:Gem::Version
125
110
  version: '0.7'
126
- - !ruby/object:Gem::Dependency
127
- name: rdoc
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ~>
132
- - !ruby/object:Gem::Version
133
- version: '3.10'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ~>
140
- - !ruby/object:Gem::Version
141
- version: '3.10'
142
111
  - !ruby/object:Gem::Dependency
143
112
  name: hoe
144
113
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
114
  requirements:
147
115
  - - ~>
148
116
  - !ruby/object:Gem::Version
149
- version: '2.13'
117
+ version: '3.12'
150
118
  type: :development
151
119
  prerelease: false
152
120
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
121
  requirements:
155
122
  - - ~>
156
123
  - !ruby/object:Gem::Version
157
- version: '2.13'
158
- description: ! 'RForce is a simple, usable binding to the Salesforce API.
124
+ version: '3.12'
125
+ description: |-
126
+ RForce is a simple, usable binding to the Salesforce API.
159
127
 
160
-
161
- {<img src="https://travis-ci.org/undees/rforce.png" />}[https://travis-ci.org/undees/rforce]'
128
+ {<img src="https://travis-ci.org/undees/rforce.png" />}[https://travis-ci.org/undees/rforce]
162
129
  email:
163
130
  - undees@gmail.com
164
131
  executables: []
@@ -166,18 +133,21 @@ extensions: []
166
133
  extra_rdoc_files:
167
134
  - History.txt
168
135
  - Manifest.txt
136
+ - README.rdoc
169
137
  files:
170
138
  - History.txt
171
139
  - Manifest.txt
172
140
  - README.rdoc
173
141
  - Rakefile
142
+ - examples/oauth_setup.rb
143
+ - examples/oauth_use.rb
144
+ - examples/simple.rb
174
145
  - lib/rforce.rb
175
146
  - lib/rforce/binding.rb
176
147
  - lib/rforce/method_keys.rb
177
148
  - lib/rforce/soap_pullable.rb
178
149
  - lib/rforce/soap_response.rb
179
150
  - lib/rforce/soap_response_expat.rb
180
- - lib/rforce/soap_response_hpricot.rb
181
151
  - lib/rforce/soap_response_nokogiri.rb
182
152
  - lib/rforce/soap_response_rexml.rb
183
153
  - lib/rforce/version.rb
@@ -187,30 +157,30 @@ files:
187
157
  - spec/spec_helper.rb
188
158
  - tasks/timing.rake
189
159
  - .gemtest
190
- homepage: http://rforce.rubyforge.org
191
- licenses: []
160
+ homepage: http://github.com/undees/rforce
161
+ licenses:
162
+ - MIT
163
+ metadata: {}
192
164
  post_install_message:
193
165
  rdoc_options:
194
166
  - --main
195
- - README.txt
167
+ - README.rdoc
196
168
  require_paths:
197
169
  - lib
198
170
  required_ruby_version: !ruby/object:Gem::Requirement
199
- none: false
200
171
  requirements:
201
- - - ! '>='
172
+ - - '>='
202
173
  - !ruby/object:Gem::Version
203
174
  version: '0'
204
175
  required_rubygems_version: !ruby/object:Gem::Requirement
205
- none: false
206
176
  requirements:
207
- - - ! '>='
177
+ - - '>='
208
178
  - !ruby/object:Gem::Version
209
179
  version: '0'
210
180
  requirements: []
211
- rubyforge_project: rforce
212
- rubygems_version: 1.8.21
181
+ rubyforge_project:
182
+ rubygems_version: 2.0.14
213
183
  signing_key:
214
- specification_version: 3
184
+ specification_version: 4
215
185
  summary: RForce is a simple, usable binding to the Salesforce API
216
186
  test_files: []
@@ -1,90 +0,0 @@
1
- require 'hpricot'
2
- require 'cgi'
3
-
4
-
5
- module RForce
6
- class SoapResponseHpricot
7
- # Parses an XML string into structured data.
8
- def initialize(content)
9
- @content = content
10
- end
11
-
12
- # Digests an XML DOM node into nested Ruby types.
13
- def parse
14
- document = Hpricot.XML(@content)
15
- node = document % 'soapenv:Body'
16
- self.class.node_to_ruby node
17
- end
18
-
19
- private
20
-
21
- def self.unescapeXML(string)
22
- CGI.unescapeHTML(string).gsub("&apos;", "'")
23
- end
24
-
25
- def self.node_to_ruby(node)
26
- # Convert text nodes into simple strings.
27
- children = (node.children || []).reject do |c|
28
- c.is_a?(Hpricot::Text) && c.to_s.strip.empty?
29
- end
30
-
31
- if node.is_a?(Hpricot::Text)
32
- return convert(SoapResponseHpricot.unescapeXML(node.inspect[1..-2]))
33
- end
34
-
35
- if children.first.is_a?(Hpricot::Text)
36
- return convert(SoapResponseHpricot.unescapeXML(children.first.inspect[1..-2]))
37
- end
38
-
39
- # Convert nodes with children into MethodHashes.
40
- elements = MethodHash.new
41
-
42
- # Add all the element's children to the hash.
43
- children.each do |e|
44
- next if e.is_a?(Hpricot::Text) && e.to_s.strip.empty?
45
- name = e.name
46
-
47
- if name.include? ':'
48
- name = name.split(':').last
49
- end
50
-
51
- name = name.to_sym
52
-
53
- case elements[name]
54
- # The most common case: unique child element tags.
55
- when NilClass then
56
- # <records> contents are always arrays
57
- elements[name] = :records == name ? [node_to_ruby(e)] : node_to_ruby(e)
58
-
59
- # Non-unique child elements become arrays:
60
-
61
- # We've already created the array: just
62
- # add the element.
63
- when Array then
64
- elements[name] << node_to_ruby(e)
65
-
66
- # We haven't created the array yet: do so,
67
- # then put the existing element in, followed
68
- # by the new one.
69
- else
70
- next if :Id == name # avoid duplicate <Id> tags
71
- elements[name] = [elements[name]]
72
- elements[name] << node_to_ruby(e)
73
- end
74
- end
75
-
76
- return elements.empty? ? nil : elements
77
- end
78
-
79
- def self.convert(string)
80
- return nil if string.nil?
81
- s = string.strip
82
-
83
- case s
84
- when '' then nil
85
- when 'true', 'false' then ('true' == s)
86
- else s
87
- end
88
- end
89
- end
90
- end