restforce 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of restforce might be problematic. Click here for more details.
- data/.travis.yml +1 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +4 -0
- data/Guardfile +11 -0
- data/README.md +19 -8
- data/lib/restforce.rb +44 -14
- data/lib/restforce/abstract_client.rb +9 -0
- data/lib/restforce/client.rb +1 -95
- data/lib/restforce/{client → concerns}/api.rb +9 -9
- data/lib/restforce/{client → concerns}/authentication.rb +9 -9
- data/lib/restforce/concerns/base.rb +58 -0
- data/lib/restforce/{client → concerns}/caching.rb +4 -4
- data/lib/restforce/concerns/canvas.rb +12 -0
- data/lib/restforce/{client → concerns}/connection.rb +13 -12
- data/lib/restforce/{client → concerns}/picklists.rb +1 -1
- data/lib/restforce/{client → concerns}/streaming.rb +3 -3
- data/lib/restforce/{client → concerns}/verbs.rb +4 -4
- data/lib/restforce/config.rb +40 -10
- data/lib/restforce/data/client.rb +18 -0
- data/lib/restforce/middleware/authentication.rb +9 -2
- data/lib/restforce/sobject.rb +1 -1
- data/lib/restforce/tooling/client.rb +13 -0
- data/lib/restforce/version.rb +1 -1
- data/spec/{lib/client_spec.rb → integration/abstract_client_spec.rb} +21 -214
- data/spec/integration/data/client_spec.rb +90 -0
- data/spec/spec_helper.rb +0 -14
- data/spec/support/client_integration.rb +45 -0
- data/spec/support/concerns.rb +18 -0
- data/spec/support/event_machine.rb +14 -0
- data/spec/support/middleware.rb +18 -1
- data/spec/unit/abstract_client_spec.rb +11 -0
- data/spec/{lib → unit}/attachment_spec.rb +3 -6
- data/spec/unit/collection_spec.rb +50 -0
- data/spec/unit/concerns/api_spec.rb +222 -0
- data/spec/unit/concerns/authentication_spec.rb +98 -0
- data/spec/unit/concerns/base_spec.rb +50 -0
- data/spec/unit/concerns/caching_spec.rb +29 -0
- data/spec/unit/concerns/canvas_spec.rb +30 -0
- data/spec/unit/concerns/connection_spec.rb +14 -0
- data/spec/{lib → unit}/config_spec.rb +13 -23
- data/spec/unit/data/client_spec.rb +10 -0
- data/spec/{lib → unit}/mash_spec.rb +0 -0
- data/spec/{lib → unit}/middleware/authentication/password_spec.rb +0 -4
- data/spec/{lib → unit}/middleware/authentication/token_spec.rb +0 -4
- data/spec/unit/middleware/authentication_spec.rb +67 -0
- data/spec/unit/middleware/authorization_spec.rb +11 -0
- data/spec/{lib → unit}/middleware/gzip_spec.rb +15 -30
- data/spec/unit/middleware/instance_url_spec.rb +24 -0
- data/spec/{lib → unit}/middleware/logger_spec.rb +4 -7
- data/spec/unit/middleware/mashify_spec.rb +11 -0
- data/spec/{lib → unit}/middleware/raise_error_spec.rb +4 -5
- data/spec/{lib → unit}/signed_request_spec.rb +0 -0
- data/spec/unit/sobject_spec.rb +68 -0
- data/spec/unit/tooling/client_spec.rb +7 -0
- metadata +75 -46
- data/lib/restforce/client/canvas.rb +0 -12
- data/spec/lib/collection_spec.rb +0 -52
- data/spec/lib/middleware/authentication_spec.rb +0 -69
- data/spec/lib/middleware/authorization_spec.rb +0 -17
- data/spec/lib/middleware/instance_url_spec.rb +0 -31
- data/spec/lib/middleware/mashify_spec.rb +0 -28
- data/spec/lib/sobject_spec.rb +0 -122
- data/spec/support/basic_client.rb +0 -37
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 1.4.0 (Jun 9, 2013)
|
2
|
+
|
3
|
+
* Added support for the tooling API.
|
4
|
+
* Fixed a bug with EMSynchrony adapter.
|
5
|
+
* Added proxy support.
|
6
|
+
|
1
7
|
## 1.3.0 (Apr 6, 2013)
|
2
8
|
|
3
9
|
* Added support for lazily traversing paginated collections #61 by @nahiluhmot.
|
@@ -59,7 +65,7 @@
|
|
59
65
|
* The http connection read/open timeout is now configurabled.
|
60
66
|
|
61
67
|
Example:
|
62
|
-
|
68
|
+
|
63
69
|
Restforce.configure do |config|
|
64
70
|
config.timeout = 300
|
65
71
|
end
|
data/Gemfile
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec', all_on_start: false, all_after_pass: false do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch('spec/spec_helper.rb') { "spec" }
|
7
|
+
|
8
|
+
watch(%r{^lib/restforce/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
9
|
+
watch(%r{^lib/restforce/(.+)\.rb$}) { |m| "spec/integration/#{m[1]}_spec.rb" }
|
10
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
11
|
+
end
|
data/README.md
CHANGED
@@ -77,7 +77,7 @@ If you prefer to use a username and password to authenticate:
|
|
77
77
|
```ruby
|
78
78
|
client = Restforce.new :username => 'foo',
|
79
79
|
:password => 'bar',
|
80
|
-
:security_token => 'security token'
|
80
|
+
:security_token => 'security token',
|
81
81
|
:client_id => 'client_id',
|
82
82
|
:client_secret => 'client_secret'
|
83
83
|
```
|
@@ -103,7 +103,7 @@ You can specify a http proxy using the :proxy_uri option, as follows:
|
|
103
103
|
```ruby
|
104
104
|
client = Restforce.new :username => 'foo',
|
105
105
|
:password => 'bar',
|
106
|
-
:security_token => 'security token'
|
106
|
+
:security_token => 'security token',
|
107
107
|
:client_id => 'client_id',
|
108
108
|
:client_secret => 'client_secret',
|
109
109
|
:proxy_uri => 'http://proxy.example.com:123'
|
@@ -118,6 +118,7 @@ You can connect to sandbox orgs by specifying a host. The default host is
|
|
118
118
|
```ruby
|
119
119
|
client = Restforce.new :host => 'test.salesforce.com'
|
120
120
|
```
|
121
|
+
The host can also be set with the environment variable SALESFORCE_HOST.
|
121
122
|
|
122
123
|
#### Global configuration
|
123
124
|
|
@@ -132,9 +133,9 @@ end
|
|
132
133
|
|
133
134
|
### Bang! methods
|
134
135
|
|
135
|
-
All the CRUD methods (create, update, upsert, destroy) have equivalent methods with
|
136
|
+
All the CRUD methods (create, update, upsert, destroy) have equivalent methods with
|
136
137
|
a ! at the end (create!, update!, upsert!, destroy!), which can be used if you need
|
137
|
-
to do some custom error handling. The bang methods will raise exceptions, while the
|
138
|
+
to do some custom error handling. The bang methods will raise exceptions, while the
|
138
139
|
non-bang methods will return false in the event that an exception is raised. This
|
139
140
|
works similarly to ActiveRecord.
|
140
141
|
|
@@ -146,7 +147,7 @@ works similarly to ActiveRecord.
|
|
146
147
|
accounts = client.query("select Id, Something__c from Account where Id = 'someid'")
|
147
148
|
# => #<Restforce::Collection >
|
148
149
|
|
149
|
-
account =
|
150
|
+
account = accounts.first
|
150
151
|
# => #<Restforce::SObject >
|
151
152
|
|
152
153
|
account.sobject_type
|
@@ -411,9 +412,10 @@ Restforce in a rails app, you can setup custom reporting to
|
|
411
412
|
[Librato](https://github.com/librato/librato-rails) using ActiveSupport::Notifications:
|
412
413
|
|
413
414
|
```ruby
|
414
|
-
client = Restforce.new
|
415
|
-
|
416
|
-
|
415
|
+
client = Restforce.new do |builder|
|
416
|
+
builder.insert_after Restforce::Middleware::InstanceURL,
|
417
|
+
FaradayMiddleware::Instrumentation, name: 'request.salesforce'
|
418
|
+
end
|
417
419
|
|
418
420
|
# config/initializers/notifications.rb
|
419
421
|
ActiveSupport::Notifications.subscribe('request.salesforce') do |*args|
|
@@ -427,6 +429,15 @@ end
|
|
427
429
|
|
428
430
|
You can use Restforce to decode signed requests from Salesforce. See [the example app](https://gist.github.com/4052312).
|
429
431
|
|
432
|
+
## Tooling API
|
433
|
+
|
434
|
+
To use the [Tooling API](http://www.salesforce.com/us/developer/docs/api_toolingpre/api_tooling.pdf),
|
435
|
+
call `Restforce.tooling` instead of `Restforce.new`:
|
436
|
+
|
437
|
+
```ruby
|
438
|
+
client = Restforce.tooling(...)
|
439
|
+
```
|
440
|
+
|
430
441
|
## Contributing
|
431
442
|
|
432
443
|
1. Fork it
|
data/lib/restforce.rb
CHANGED
@@ -6,24 +6,54 @@ require 'restforce/version'
|
|
6
6
|
require 'restforce/config'
|
7
7
|
|
8
8
|
module Restforce
|
9
|
-
autoload :
|
10
|
-
autoload :
|
11
|
-
autoload :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
autoload :AbstractClient, 'restforce/abstract_client'
|
10
|
+
autoload :SignedRequest, 'restforce/signed_request'
|
11
|
+
autoload :Collection, 'restforce/collection'
|
12
|
+
autoload :Middleware, 'restforce/middleware'
|
13
|
+
autoload :Attachment, 'restforce/attachment'
|
14
|
+
autoload :UploadIO, 'restforce/upload_io'
|
15
|
+
autoload :SObject, 'restforce/sobject'
|
16
|
+
autoload :Client, 'restforce/client'
|
17
|
+
autoload :Mash, 'restforce/mash'
|
18
|
+
|
19
|
+
module Concerns
|
20
|
+
autoload :Authentication, 'restforce/concerns/authentication'
|
21
|
+
autoload :Connection, 'restforce/concerns/connection'
|
22
|
+
autoload :Picklists, 'restforce/concerns/picklists'
|
23
|
+
autoload :Streaming, 'restforce/concerns/streaming'
|
24
|
+
autoload :Caching, 'restforce/concerns/caching'
|
25
|
+
autoload :Canvas, 'restforce/concerns/canvas'
|
26
|
+
autoload :Verbs, 'restforce/concerns/verbs'
|
27
|
+
autoload :Base, 'restforce/concerns/base'
|
28
|
+
autoload :API, 'restforce/concerns/api'
|
29
|
+
end
|
30
|
+
|
31
|
+
module Data
|
32
|
+
autoload :Client, 'restforce/data/client'
|
33
|
+
end
|
34
|
+
|
35
|
+
module Tooling
|
36
|
+
autoload :Client, 'restforce/tooling/client'
|
37
|
+
end
|
38
|
+
|
39
|
+
Error = Class.new(StandardError)
|
40
|
+
AuthenticationError = Class.new(Error)
|
41
|
+
UnauthorizedError = Class.new(Error)
|
20
42
|
|
21
43
|
class << self
|
22
|
-
# Alias for Restforce::Client.new
|
44
|
+
# Alias for Restforce::Data::Client.new
|
23
45
|
#
|
24
46
|
# Shamelessly pulled from https://github.com/pengwynn/octokit/blob/master/lib/octokit.rb
|
25
|
-
def new(
|
26
|
-
|
47
|
+
def new(*args)
|
48
|
+
data(*args)
|
49
|
+
end
|
50
|
+
|
51
|
+
def data(*args)
|
52
|
+
Restforce::Data::Client.new(*args)
|
53
|
+
end
|
54
|
+
|
55
|
+
def tooling(*args)
|
56
|
+
Restforce::Tooling::Client.new(*args)
|
27
57
|
end
|
28
58
|
|
29
59
|
# Helper for decoding signed requests.
|
data/lib/restforce/client.rb
CHANGED
@@ -1,97 +1,3 @@
|
|
1
|
-
require 'restforce/client/connection'
|
2
|
-
require 'restforce/client/authentication'
|
3
|
-
require 'restforce/client/streaming'
|
4
|
-
require 'restforce/client/picklists'
|
5
|
-
require 'restforce/client/caching'
|
6
|
-
require 'restforce/client/canvas'
|
7
|
-
require 'restforce/client/api'
|
8
|
-
|
9
1
|
module Restforce
|
10
|
-
|
11
|
-
include Restforce::Client::Connection
|
12
|
-
include Restforce::Client::Authentication
|
13
|
-
include Restforce::Client::Streaming
|
14
|
-
include Restforce::Client::Picklists
|
15
|
-
include Restforce::Client::Caching
|
16
|
-
include Restforce::Client::Canvas
|
17
|
-
include Restforce::Client::API
|
18
|
-
|
19
|
-
# Public: Creates a new client instance
|
20
|
-
#
|
21
|
-
# opts - A hash of options to be passed in (default: {}).
|
22
|
-
# :username - The String username to use (required for password authentication).
|
23
|
-
# :password - The String password to use (required for password authentication).
|
24
|
-
# :security_token - The String security token to use (required for password authentication).
|
25
|
-
#
|
26
|
-
# :oauth_token - The String oauth access token to authenticate api
|
27
|
-
# calls (required unless password
|
28
|
-
# authentication is used).
|
29
|
-
# :refresh_token - The String refresh token to obtain fresh
|
30
|
-
# oauth access tokens (required if oauth
|
31
|
-
# authentication is used).
|
32
|
-
# :instance_url - The String base url for all api requests
|
33
|
-
# (required if oauth authentication is used).
|
34
|
-
#
|
35
|
-
# :client_id - The oauth client id to use. Needed for both
|
36
|
-
# password and oauth authentication
|
37
|
-
# :client_secret - The oauth client secret to use.
|
38
|
-
#
|
39
|
-
# :host - The String hostname to use during
|
40
|
-
# authentication requests (default: 'login.salesforce.com').
|
41
|
-
#
|
42
|
-
# :api_version - The String REST api version to use (default: '24.0')
|
43
|
-
#
|
44
|
-
# :authentication_retries - The number of times that client
|
45
|
-
# should attempt to reauthenticate
|
46
|
-
# before raising an exception (default: 3).
|
47
|
-
#
|
48
|
-
# :compress - Set to true to have Salesforce compress the response (default: false).
|
49
|
-
# :timeout - Faraday connection request read/open timeout. (default: nil).
|
50
|
-
#
|
51
|
-
# :proxy_uri - Proxy URI: 'http://proxy.example.com:port' or 'http://user@pass:proxy.example.com:port'
|
52
|
-
#
|
53
|
-
# Examples
|
54
|
-
#
|
55
|
-
# # Initialize a new client using password authentication:
|
56
|
-
# Restforce::Client.new :username => 'user',
|
57
|
-
# :password => 'pass',
|
58
|
-
# :security_token => 'security token',
|
59
|
-
# :client_id => 'client id',
|
60
|
-
# :client_secret => 'client secret'
|
61
|
-
#
|
62
|
-
# # Initialize a new client using oauth authentication:
|
63
|
-
# Restforce::Client.new :oauth_token => 'access token',
|
64
|
-
# :refresh_token => 'refresh token',
|
65
|
-
# :instance_url => 'https://na1.salesforce.com',
|
66
|
-
# :client_id => 'client id',
|
67
|
-
# :client_secret => 'client secret'
|
68
|
-
#
|
69
|
-
# # Initialize a new client without using any authentication middleware:
|
70
|
-
# Restforce::Client.new :oauth_token => 'access token',
|
71
|
-
# :instance_url => 'https://na1.salesforce.com'
|
72
|
-
#
|
73
|
-
def initialize(opts = {})
|
74
|
-
raise 'Please specify a hash of options' unless opts.is_a?(Hash)
|
75
|
-
@options = Hash[Restforce.configuration.options.map { |option| [option, Restforce.configuration.send(option)] }]
|
76
|
-
@options.merge! opts
|
77
|
-
end
|
78
|
-
|
79
|
-
def instance_url
|
80
|
-
authenticate! unless @options[:instance_url]
|
81
|
-
@options[:instance_url]
|
82
|
-
end
|
83
|
-
|
84
|
-
# Public: Returns a url to the resource.
|
85
|
-
#
|
86
|
-
# resource - A record that responds to to_sparam or a String/Fixnum.
|
87
|
-
#
|
88
|
-
# Returns the url to the resource.
|
89
|
-
def url(resource)
|
90
|
-
"#{instance_url}/#{(resource.respond_to?(:to_sparam) ? resource.to_sparam : resource)}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def inspect
|
94
|
-
"#<#{self.class} @options=#{@options.inspect}>"
|
95
|
-
end
|
96
|
-
end
|
2
|
+
Client = Data::Client
|
97
3
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'restforce/
|
1
|
+
require 'restforce/concerns/verbs'
|
2
2
|
|
3
3
|
module Restforce
|
4
|
-
|
4
|
+
module Concerns
|
5
5
|
module API
|
6
|
-
extend Restforce::
|
6
|
+
extend Restforce::Concerns::Verbs
|
7
7
|
|
8
8
|
# Public: Helper methods for performing arbitrary actions against the API using
|
9
9
|
# various HTTP verbs.
|
@@ -41,7 +41,7 @@ module Restforce
|
|
41
41
|
def list_sobjects
|
42
42
|
describe.collect { |sobject| sobject['name'] }
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Public: Returns a detailed describe result for the specified sobject
|
46
46
|
#
|
47
47
|
# sobject - Stringish name of the sobject (default: nil).
|
@@ -76,7 +76,7 @@ module Restforce
|
|
76
76
|
def org_id
|
77
77
|
query('select id from Organization').first['Id']
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
# Public: Executs a SOQL query and returns the result.
|
81
81
|
#
|
82
82
|
# soql - A SOQL expression.
|
@@ -93,7 +93,7 @@ module Restforce
|
|
93
93
|
response = api_get 'query', :q => soql
|
94
94
|
mashify? ? response.body : response.body['records']
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# Public: Perform a SOSL search
|
98
98
|
#
|
99
99
|
# sosl - A SOSL expression.
|
@@ -113,7 +113,7 @@ module Restforce
|
|
113
113
|
def search(sosl)
|
114
114
|
api_get('search', :q => sosl).body
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
# Public: Insert a new record.
|
118
118
|
#
|
119
119
|
# sobject - String name of the sobject.
|
@@ -184,7 +184,7 @@ module Restforce
|
|
184
184
|
# Raises an exception if an error is returned from Salesforce.
|
185
185
|
def update!(sobject, attrs)
|
186
186
|
id = attrs.delete(attrs.keys.find { |k| k.to_s.downcase == 'id' })
|
187
|
-
raise 'Id field missing.' unless id
|
187
|
+
raise ArgumentError, 'Id field missing from attrs.' unless id
|
188
188
|
api_patch "sobjects/#{sobject}/#{id}", attrs
|
189
189
|
true
|
190
190
|
end
|
@@ -285,7 +285,7 @@ module Restforce
|
|
285
285
|
# api_path('sobjects')
|
286
286
|
# # => '/services/data/v24.0/sobjects'
|
287
287
|
def api_path(path)
|
288
|
-
"/services/data/v#{
|
288
|
+
"/services/data/v#{options[:api_version]}/#{path}"
|
289
289
|
end
|
290
290
|
|
291
291
|
# Internal: Errors that should be rescued from in non-bang methods
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Restforce
|
2
|
-
|
2
|
+
module Concerns
|
3
3
|
module Authentication
|
4
4
|
|
5
5
|
# Public: Force an authentication
|
6
6
|
def authenticate!
|
7
7
|
raise AuthenticationError, 'No authentication middleware present' unless authentication_middleware
|
8
|
-
middleware = authentication_middleware.new nil, self,
|
8
|
+
middleware = authentication_middleware.new nil, self, options
|
9
9
|
middleware.authenticate!
|
10
10
|
end
|
11
11
|
|
@@ -21,18 +21,18 @@ module Restforce
|
|
21
21
|
# Internal: Returns true if username/password (autonomous) flow should be used for
|
22
22
|
# authentication.
|
23
23
|
def username_password?
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
options[:username] &&
|
25
|
+
options[:password] &&
|
26
|
+
options[:client_id] &&
|
27
|
+
options[:client_secret]
|
28
28
|
end
|
29
29
|
|
30
30
|
# Internal: Returns true if oauth token refresh flow should be used for
|
31
31
|
# authentication.
|
32
32
|
def oauth_refresh?
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
options[:refresh_token] &&
|
34
|
+
options[:client_id] &&
|
35
|
+
options[:client_secret]
|
36
36
|
end
|
37
37
|
|
38
38
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Restforce
|
2
|
+
module Concerns
|
3
|
+
module Base
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
# Public: Creates a new client instance
|
8
|
+
#
|
9
|
+
# opts - A hash of options to be passed in (default: {}).
|
10
|
+
# :username - The String username to use (required for password authentication).
|
11
|
+
# :password - The String password to use (required for password authentication).
|
12
|
+
# :security_token - The String security token to use (required for password authentication).
|
13
|
+
#
|
14
|
+
# :oauth_token - The String oauth access token to authenticate api
|
15
|
+
# calls (required unless password
|
16
|
+
# authentication is used).
|
17
|
+
# :refresh_token - The String refresh token to obtain fresh
|
18
|
+
# oauth access tokens (required if oauth
|
19
|
+
# authentication is used).
|
20
|
+
# :instance_url - The String base url for all api requests
|
21
|
+
# (required if oauth authentication is used).
|
22
|
+
#
|
23
|
+
# :client_id - The oauth client id to use. Needed for both
|
24
|
+
# password and oauth authentication
|
25
|
+
# :client_secret - The oauth client secret to use.
|
26
|
+
#
|
27
|
+
# :host - The String hostname to use during
|
28
|
+
# authentication requests (default: 'login.salesforce.com').
|
29
|
+
#
|
30
|
+
# :api_version - The String REST api version to use (default: '24.0')
|
31
|
+
#
|
32
|
+
# :authentication_retries - The number of times that client
|
33
|
+
# should attempt to reauthenticate
|
34
|
+
# before raising an exception (default: 3).
|
35
|
+
#
|
36
|
+
# :compress - Set to true to have Salesforce compress the response (default: false).
|
37
|
+
# :timeout - Faraday connection request read/open timeout. (default: nil).
|
38
|
+
#
|
39
|
+
# :proxy_uri - Proxy URI: 'http://proxy.example.com:port' or 'http://user@pass:proxy.example.com:port'
|
40
|
+
def initialize(opts = {})
|
41
|
+
raise ArgumentError, 'Please specify a hash of options' unless opts.is_a?(Hash)
|
42
|
+
@options = Hash[Restforce.configuration.options.map { |option| [option, Restforce.configuration.send(option)] }]
|
43
|
+
@options.merge! opts
|
44
|
+
yield builder if block_given?
|
45
|
+
end
|
46
|
+
|
47
|
+
def instance_url
|
48
|
+
authenticate! unless options[:instance_url]
|
49
|
+
options[:instance_url]
|
50
|
+
end
|
51
|
+
|
52
|
+
def inspect
|
53
|
+
"#<#{self.class} @options=#{@options.inspect}>"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|