rforce 0.4.1 → 0.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.
- data/History.txt +11 -0
- data/Rakefile +2 -2
- data/lib/rforce/binding.rb +64 -21
- data/lib/rforce/soap_pullable.rb +2 -2
- data/lib/rforce/soap_response_expat.rb +2 -1
- data/lib/rforce/soap_response_hpricot.rb +1 -1
- data/lib/rforce/soap_response_rexml.rb +4 -3
- data/lib/rforce/version.rb +1 -1
- data/spec/rforce_spec.rb +22 -2
- metadata +47 -30
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.5.1 2010-12-11
|
2
|
+
|
3
|
+
* 2 minor enhancements:
|
4
|
+
* Increase batch size (Raymond Gao)
|
5
|
+
* Removed Facets dependency (Justin Ramos, Aaron Qian)
|
6
|
+
|
7
|
+
== 0.4.1 2010-03-21
|
8
|
+
|
9
|
+
* 1 minor enhancement:
|
10
|
+
* Experimental OAuth support
|
11
|
+
|
1
12
|
== 0.4 2010-01-21
|
2
13
|
|
3
14
|
* 1 minor enhancement:
|
data/Rakefile
CHANGED
@@ -8,8 +8,8 @@ require 'rforce/version'
|
|
8
8
|
|
9
9
|
Hoe.new('rforce', RForce::VERSION) do |p|
|
10
10
|
p.developer 'Ian Dees', 'undees@gmail.com'
|
11
|
-
p.extra_deps = [['builder', '
|
12
|
-
p.extra_dev_deps = [['rspec', '
|
11
|
+
p.extra_deps = [['builder', '~> 2.0']]
|
12
|
+
p.extra_dev_deps = [['rspec', '~> 1.3']]
|
13
13
|
p.remote_rdoc_dir = ''
|
14
14
|
p.rspec_options = ['-rubygems', '--options', 'spec/spec.opts']
|
15
15
|
end
|
data/lib/rforce/binding.rb
CHANGED
@@ -2,16 +2,19 @@ require 'net/https'
|
|
2
2
|
require 'uri'
|
3
3
|
require 'zlib'
|
4
4
|
require 'stringio'
|
5
|
+
require 'rexml/document'
|
5
6
|
require 'builder'
|
6
|
-
|
7
|
+
require 'oauth'
|
7
8
|
|
8
9
|
module RForce
|
9
10
|
# Implements the connection to the SalesForce server.
|
10
11
|
class Binding
|
11
12
|
include RForce
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
|
14
|
+
# Increase the maximum fetch size to 2000, as allowed by Salesforce
|
15
|
+
# Added by Raymond Gao
|
16
|
+
DEFAULT_BATCH_SIZE = 2000
|
17
|
+
attr_accessor :batch_size, :url, :assignment_rule_id, :use_default_rule, :update_mru, :client_id, :trigger_user_email,
|
15
18
|
:trigger_other_email, :trigger_auto_response_email
|
16
19
|
|
17
20
|
# Fill in the guts of this typical SOAP envelope
|
@@ -43,12 +46,15 @@ module RForce
|
|
43
46
|
MruHeader = '<partner:MruHeader soap:mustUnderstand="1"><partner:updateMru>true</partner:updateMru></partner:MruHeader>'
|
44
47
|
ClientIdHeader = '<partner:CallOptions soap:mustUnderstand="1"><partner:client>%s</partner:client></partner:CallOptions>'
|
45
48
|
|
46
|
-
# Connect to the server securely.
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
# Connect to the server securely. If you pass an oauth hash, it
|
50
|
+
# must contain the keys :consumer_key, :consumer_secret,
|
51
|
+
# :access_token, :access_secret, and :login_url.
|
52
|
+
def initialize(url, sid = nil, oauth = nil)
|
50
53
|
@session_id = sid
|
54
|
+
@oauth = oauth
|
51
55
|
@batch_size = DEFAULT_BATCH_SIZE
|
56
|
+
|
57
|
+
init_server(url)
|
52
58
|
end
|
53
59
|
|
54
60
|
|
@@ -59,23 +65,42 @@ module RForce
|
|
59
65
|
|
60
66
|
def init_server(url)
|
61
67
|
@url = URI.parse(url)
|
62
|
-
@server = Net::HTTP.new(@url.host, @url.port)
|
63
|
-
@server.use_ssl = @url.scheme == 'https'
|
64
|
-
@server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
65
68
|
|
66
|
-
|
67
|
-
|
69
|
+
if (@oauth)
|
70
|
+
consumer = OAuth::Consumer.new \
|
71
|
+
@oauth[:consumer_key],
|
72
|
+
@oauth[:consumer_secret],
|
73
|
+
{ :site => url }
|
74
|
+
|
75
|
+
consumer.http.set_debug_output $stderr if show_debug
|
76
|
+
|
77
|
+
@server = OAuth::AccessToken.new \
|
78
|
+
consumer,
|
79
|
+
@oauth[:access_token],
|
80
|
+
@oauth[:access_secret]
|
81
|
+
|
82
|
+
class << @server
|
83
|
+
alias_method :post2, :post
|
84
|
+
end
|
85
|
+
else
|
86
|
+
@server = Net::HTTP.new(@url.host, @url.port)
|
87
|
+
@server.use_ssl = @url.scheme == 'https'
|
88
|
+
@server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
89
|
+
|
90
|
+
# run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
|
91
|
+
@server.set_debug_output $stderr if show_debug
|
92
|
+
end
|
68
93
|
end
|
69
94
|
|
70
95
|
|
71
|
-
# Log in to the server
|
72
|
-
# returned to us by SalesForce.
|
96
|
+
# Log in to the server with a user name and password, remembering
|
97
|
+
# the session ID returned to us by SalesForce.
|
73
98
|
def login(user, password)
|
74
99
|
@user = user
|
75
100
|
@password = password
|
76
101
|
|
77
102
|
response = call_remote(:login, [:username, user, :password, password])
|
78
|
-
|
103
|
+
|
79
104
|
raise "Incorrect user name / password [#{response.fault}]" unless response.loginResponse
|
80
105
|
|
81
106
|
result = response[:loginResponse][:result]
|
@@ -86,6 +111,25 @@ module RForce
|
|
86
111
|
response
|
87
112
|
end
|
88
113
|
|
114
|
+
# Log in to the server with OAuth, remembering
|
115
|
+
# the session ID returned to us by SalesForce.
|
116
|
+
def login_with_oauth
|
117
|
+
result = @server.post @oauth[:login_url], '', {}
|
118
|
+
|
119
|
+
case result
|
120
|
+
when Net::HTTPSuccess
|
121
|
+
doc = REXML::Document.new result.body
|
122
|
+
@session_id = doc.elements['*/sessionId'].text
|
123
|
+
server_url = doc.elements['*/serverUrl'].text
|
124
|
+
init_server server_url
|
125
|
+
|
126
|
+
return {:sessionId => @sessionId, :serverUrl => server_url}
|
127
|
+
when Net::HTTPUnauthorized
|
128
|
+
raise 'Invalid OAuth tokens'
|
129
|
+
else
|
130
|
+
raise "Unexpected error: #{response.inspect}"
|
131
|
+
end
|
132
|
+
end
|
89
133
|
|
90
134
|
# Call a method on the remote server. Arguments can be
|
91
135
|
# a hash or (if order is important) an array of alternating
|
@@ -104,21 +148,21 @@ module RForce
|
|
104
148
|
extra_headers << AssignmentRuleHeaderUsingDefaultRule if use_default_rule
|
105
149
|
extra_headers << MruHeader if update_mru
|
106
150
|
extra_headers << (ClientIdHeader % client_id) if client_id
|
107
|
-
|
151
|
+
|
108
152
|
if trigger_user_email or trigger_other_email or trigger_auto_response_email
|
109
153
|
extra_headers << '<partner:EmailHeader soap:mustUnderstand="1">'
|
110
|
-
|
154
|
+
|
111
155
|
extra_headers << '<partner:triggerUserEmail>true</partner:triggerUserEmail>' if trigger_user_email
|
112
156
|
extra_headers << '<partner:triggerOtherEmail>true</partner:triggerOtherEmail>' if trigger_other_email
|
113
157
|
extra_headers << '<partner:triggerAutoResponseEmail>true</partner:triggerAutoResponseEmail>' if trigger_auto_response_email
|
114
|
-
|
158
|
+
|
115
159
|
extra_headers << '</partner:EmailHeader>'
|
116
160
|
end
|
117
161
|
|
118
162
|
# Fill in the blanks of the SOAP envelope with our
|
119
163
|
# session ID and the expanded XML of our request.
|
120
164
|
request = (Envelope % [@session_id, @batch_size, extra_headers, expanded])
|
121
|
-
|
165
|
+
|
122
166
|
# reset the batch size for the next request
|
123
167
|
@batch_size = DEFAULT_BATCH_SIZE
|
124
168
|
|
@@ -209,4 +253,3 @@ module RForce
|
|
209
253
|
end
|
210
254
|
end
|
211
255
|
end
|
212
|
-
|
data/lib/rforce/soap_pullable.rb
CHANGED
@@ -4,6 +4,7 @@ require 'rforce/soap_pullable'
|
|
4
4
|
module RForce
|
5
5
|
class SoapResponseExpat
|
6
6
|
include SoapPullable
|
7
|
+
include MethodKeys
|
7
8
|
|
8
9
|
def initialize(content)
|
9
10
|
@content = content
|
@@ -12,7 +13,7 @@ module RForce
|
|
12
13
|
def parse
|
13
14
|
@current_value = nil
|
14
15
|
@stack = []
|
15
|
-
@parsed =
|
16
|
+
@parsed = {}
|
16
17
|
@done = false
|
17
18
|
@namespaces = []
|
18
19
|
|
@@ -8,6 +8,7 @@ module RForce
|
|
8
8
|
# object whose methods correspond to nested XML elements.
|
9
9
|
class SoapResponseRexml
|
10
10
|
include SoapPullable
|
11
|
+
include MethodKeys
|
11
12
|
|
12
13
|
%w(attlistdecl cdata comment doctype doctype_end elementdecl
|
13
14
|
entity entitydecl instruction notationdecl xmldecl).each do |unused|
|
@@ -17,17 +18,17 @@ module RForce
|
|
17
18
|
def initialize(content)
|
18
19
|
@content = content
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
# Parses an XML string into structured data.
|
22
23
|
def parse
|
23
24
|
@current_value = nil
|
24
25
|
@stack = []
|
25
|
-
@parsed =
|
26
|
+
@parsed = {}
|
26
27
|
@done = false
|
27
28
|
@namespaces = []
|
28
29
|
|
29
30
|
REXML::Document.parse_stream @content, self
|
30
|
-
|
31
|
+
|
31
32
|
@parsed
|
32
33
|
end
|
33
34
|
end
|
data/lib/rforce/version.rb
CHANGED
data/spec/rforce_spec.rb
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
describe MethodKeys do
|
4
|
+
it 'lets you access hash keys with methods' do
|
5
|
+
h = {:foo => :bar}
|
6
|
+
class << h; include MethodKeys; end
|
7
|
+
|
8
|
+
h.foo.should == :bar
|
9
|
+
h.nonexistent.should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'provides a Hash-like class' do
|
13
|
+
mh = MethodHash.new
|
14
|
+
mh[:one] = 1
|
15
|
+
mh[:ten] = 10
|
16
|
+
|
17
|
+
mh.one.should == 1
|
18
|
+
mh.ten.should == 10
|
19
|
+
mh.nothing.should be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
3
23
|
describe 'expand' do
|
4
24
|
it 'turns Ruby into XML' do
|
5
25
|
xmlns = 'urn:partner.soap.sforce.com'
|
@@ -35,7 +55,7 @@ describe 'a SoapResponse implementation' do
|
|
35
55
|
|
36
56
|
results = begin
|
37
57
|
klass = RForce.const_get name
|
38
|
-
klass.new(@contents).parse.queryResponse
|
58
|
+
klass.new(@contents).parse.queryResponse[:result][:records]
|
39
59
|
rescue NameError
|
40
60
|
nil
|
41
61
|
end
|
@@ -76,7 +96,7 @@ describe 'a SoapResponse implementation' do
|
|
76
96
|
pending 'expat not installed' unless @expat_recs
|
77
97
|
@expat_recs.first.Description.should == expected
|
78
98
|
|
79
|
-
pending 'hpricot not installed' unless @
|
99
|
+
pending 'hpricot not installed' unless @hpricot_recs
|
80
100
|
@hpricot_recs.first.Description.should == expected
|
81
101
|
end
|
82
102
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rforce
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 1
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
version: "0.5"
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Ian Dees
|
@@ -9,49 +14,55 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-12-11 00:00:00 -08:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: builder
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
20
25
|
requirements:
|
21
|
-
- -
|
26
|
+
- - ~>
|
22
27
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
25
|
-
-
|
26
|
-
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
- 0
|
32
|
+
version: "2.0"
|
27
33
|
type: :runtime
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "2.4"
|
34
|
-
version:
|
34
|
+
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rspec
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 9
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 3
|
43
47
|
version: "1.3"
|
44
|
-
|
48
|
+
type: :development
|
49
|
+
version_requirements: *id002
|
45
50
|
- !ruby/object:Gem::Dependency
|
46
51
|
name: hoe
|
47
|
-
|
48
|
-
|
49
|
-
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
50
55
|
requirements:
|
51
56
|
- - ">="
|
52
57
|
- !ruby/object:Gem::Version
|
53
|
-
|
54
|
-
|
58
|
+
hash: 47
|
59
|
+
segments:
|
60
|
+
- 2
|
61
|
+
- 8
|
62
|
+
- 0
|
63
|
+
version: 2.8.0
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
55
66
|
description: RForce is a simple, usable binding to the SalesForce API.
|
56
67
|
email:
|
57
68
|
- undees@gmail.com
|
@@ -92,21 +103,27 @@ rdoc_options:
|
|
92
103
|
require_paths:
|
93
104
|
- lib
|
94
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
95
107
|
requirements:
|
96
108
|
- - ">="
|
97
109
|
- !ruby/object:Gem::Version
|
110
|
+
hash: 3
|
111
|
+
segments:
|
112
|
+
- 0
|
98
113
|
version: "0"
|
99
|
-
version:
|
100
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
101
116
|
requirements:
|
102
117
|
- - ">="
|
103
118
|
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
104
122
|
version: "0"
|
105
|
-
version:
|
106
123
|
requirements: []
|
107
124
|
|
108
125
|
rubyforge_project: rforce
|
109
|
-
rubygems_version: 1.3.
|
126
|
+
rubygems_version: 1.3.7
|
110
127
|
signing_key:
|
111
128
|
specification_version: 3
|
112
129
|
summary: RForce is a simple, usable binding to the SalesForce API.
|