rforce 0.4.1 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
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.