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 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', '>= 2.0.0'], ['facets', '>= 2.4']]
12
- p.extra_dev_deps = [['rspec', '>= 1.3']]
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
@@ -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
- DEFAULT_BATCH_SIZE = 10
14
- attr_accessor :batch_size, :url, :assignment_rule_id, :use_default_rule, :update_mru, :client_id, :trigger_user_email,
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
- def initialize(url, sid = nil)
48
- init_server(url)
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
- # run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
67
- @server.set_debug_output $stderr if show_debug
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 and remember the session ID
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
-
@@ -1,4 +1,4 @@
1
- require 'facets/openhash'
1
+ require 'rforce/method_keys'
2
2
 
3
3
  module RForce
4
4
  module SoapPullable
@@ -19,7 +19,7 @@ module RForce
19
19
  return
20
20
  end
21
21
 
22
- @stack.push OpenHash.new({})
22
+ @stack.push(MethodHash.new)
23
23
  end
24
24
 
25
25
  def text(data)
@@ -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 = OpenHash.new({})
16
+ @parsed = {}
16
17
  @done = false
17
18
  @namespaces = []
18
19
 
@@ -37,7 +37,7 @@ module RForce
37
37
  end
38
38
 
39
39
  # Convert nodes with children into MethodHashes.
40
- elements = OpenHash.new({})
40
+ elements = MethodHash.new
41
41
 
42
42
  # Add all the element's children to the hash.
43
43
  children.each do |e|
@@ -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 = OpenHash.new({})
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
@@ -1,3 +1,3 @@
1
1
  module RForce
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5'
3
3
  end
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.result.records
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 @hpricot
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
- version: 0.4.1
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-03-12 00:00:00 -08:00
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
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
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
- version: 2.0.0
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: facets
28
+ hash: 3
29
+ segments:
30
+ - 2
31
+ - 0
32
+ version: "2.0"
27
33
  type: :runtime
28
- version_requirement:
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
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
48
+ type: :development
49
+ version_requirements: *id002
45
50
  - !ruby/object:Gem::Dependency
46
51
  name: hoe
47
- type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
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
- version: 2.5.0
54
- version:
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.5
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.