force 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +96 -0
  3. data/Gemfile +11 -0
  4. data/Gemfile.lock +107 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE +22 -0
  7. data/README.md +421 -0
  8. data/Rakefile +10 -0
  9. data/coverage/assets/0.7.1/application.css +1110 -0
  10. data/coverage/assets/0.7.1/application.js +626 -0
  11. data/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  12. data/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  13. data/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  14. data/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  15. data/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  16. data/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  17. data/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  18. data/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  19. data/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  20. data/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  21. data/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  22. data/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  23. data/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  24. data/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  25. data/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  26. data/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  27. data/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  28. data/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  29. data/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  30. data/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  31. data/coverage/assets/0.7.1/favicon_green.png +0 -0
  32. data/coverage/assets/0.7.1/favicon_red.png +0 -0
  33. data/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  34. data/coverage/assets/0.7.1/loading.gif +0 -0
  35. data/coverage/assets/0.7.1/magnify.png +0 -0
  36. data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  37. data/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  38. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  39. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  40. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  41. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  42. data/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  43. data/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  44. data/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  45. data/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  46. data/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  47. data/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  48. data/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  49. data/coverage/index.html +19808 -0
  50. data/force.gemspec +27 -0
  51. data/lib/force.rb +74 -0
  52. data/lib/force/abstract_client.rb +9 -0
  53. data/lib/force/attachment.rb +21 -0
  54. data/lib/force/client.rb +3 -0
  55. data/lib/force/collection.rb +45 -0
  56. data/lib/force/concerns/api.rb +321 -0
  57. data/lib/force/concerns/authentication.rb +39 -0
  58. data/lib/force/concerns/base.rb +59 -0
  59. data/lib/force/concerns/caching.rb +24 -0
  60. data/lib/force/concerns/canvas.rb +10 -0
  61. data/lib/force/concerns/connection.rb +74 -0
  62. data/lib/force/concerns/picklists.rb +87 -0
  63. data/lib/force/concerns/streaming.rb +31 -0
  64. data/lib/force/concerns/verbs.rb +67 -0
  65. data/lib/force/config.rb +140 -0
  66. data/lib/force/data/client.rb +18 -0
  67. data/lib/force/mash.rb +66 -0
  68. data/lib/force/middleware.rb +27 -0
  69. data/lib/force/middleware/authentication.rb +73 -0
  70. data/lib/force/middleware/authentication/password.rb +17 -0
  71. data/lib/force/middleware/authentication/token.rb +15 -0
  72. data/lib/force/middleware/authorization.rb +15 -0
  73. data/lib/force/middleware/caching.rb +22 -0
  74. data/lib/force/middleware/gzip.rb +31 -0
  75. data/lib/force/middleware/instance_url.rb +14 -0
  76. data/lib/force/middleware/logger.rb +40 -0
  77. data/lib/force/middleware/mashify.rb +16 -0
  78. data/lib/force/middleware/multipart.rb +55 -0
  79. data/lib/force/middleware/raise_error.rb +25 -0
  80. data/lib/force/signed_request.rb +48 -0
  81. data/lib/force/sobject.rb +68 -0
  82. data/lib/force/tooling/client.rb +11 -0
  83. data/lib/force/upload_io.rb +20 -0
  84. data/lib/force/version.rb +3 -0
  85. data/spec/fixtures/auth_error_response.json +4 -0
  86. data/spec/fixtures/auth_success_response.json +7 -0
  87. data/spec/fixtures/blob.jpg +0 -0
  88. data/spec/fixtures/expired_session_response.json +6 -0
  89. data/spec/fixtures/reauth_success_response.json +7 -0
  90. data/spec/fixtures/refresh_error_response.json +4 -0
  91. data/spec/fixtures/refresh_success_response.json +7 -0
  92. data/spec/fixtures/services_data_success_response.json +12 -0
  93. data/spec/fixtures/sobject/create_success_response.json +5 -0
  94. data/spec/fixtures/sobject/delete_error_response.json +1 -0
  95. data/spec/fixtures/sobject/describe_sobjects_success_response.json +31 -0
  96. data/spec/fixtures/sobject/list_sobjects_success_response.json +31 -0
  97. data/spec/fixtures/sobject/org_query_response.json +11 -0
  98. data/spec/fixtures/sobject/query_aggregate_success_response.json +23 -0
  99. data/spec/fixtures/sobject/query_empty_response.json +5 -0
  100. data/spec/fixtures/sobject/query_error_response.json +6 -0
  101. data/spec/fixtures/sobject/query_paginated_first_page_response.json +14 -0
  102. data/spec/fixtures/sobject/query_paginated_last_page_response.json +13 -0
  103. data/spec/fixtures/sobject/query_success_response.json +38 -0
  104. data/spec/fixtures/sobject/recent_success_response.json +18 -0
  105. data/spec/fixtures/sobject/search_error_response.json +6 -0
  106. data/spec/fixtures/sobject/search_success_response.json +16 -0
  107. data/spec/fixtures/sobject/sobject_describe_error_response.json +6 -0
  108. data/spec/fixtures/sobject/sobject_describe_success_response.json +1429 -0
  109. data/spec/fixtures/sobject/sobject_find_error_response.json +6 -0
  110. data/spec/fixtures/sobject/sobject_find_success_response.json +29 -0
  111. data/spec/fixtures/sobject/upsert_created_success_response.json +5 -0
  112. data/spec/fixtures/sobject/upsert_error_response.json +6 -0
  113. data/spec/fixtures/sobject/upsert_multiple_error_response.json +4 -0
  114. data/spec/fixtures/sobject/upsert_updated_success_response.json +0 -0
  115. data/spec/fixtures/sobject/write_error_response.json +6 -0
  116. data/spec/integration/abstract_client_spec.rb +306 -0
  117. data/spec/integration/data/client_spec.rb +90 -0
  118. data/spec/spec_helper.rb +20 -0
  119. data/spec/support/client_integration.rb +45 -0
  120. data/spec/support/concerns.rb +18 -0
  121. data/spec/support/event_machine.rb +14 -0
  122. data/spec/support/fixture_helpers.rb +45 -0
  123. data/spec/support/matchers.rb +11 -0
  124. data/spec/support/middleware.rb +76 -0
  125. data/spec/support/mock_cache.rb +13 -0
  126. data/spec/unit/abstract_client_spec.rb +11 -0
  127. data/spec/unit/attachment_spec.rb +15 -0
  128. data/spec/unit/collection_spec.rb +52 -0
  129. data/spec/unit/concerns/api_spec.rb +244 -0
  130. data/spec/unit/concerns/authentication_spec.rb +98 -0
  131. data/spec/unit/concerns/base_spec.rb +42 -0
  132. data/spec/unit/concerns/caching_spec.rb +29 -0
  133. data/spec/unit/concerns/canvas_spec.rb +30 -0
  134. data/spec/unit/concerns/connection_spec.rb +22 -0
  135. data/spec/unit/config_spec.rb +99 -0
  136. data/spec/unit/data/client_spec.rb +10 -0
  137. data/spec/unit/mash_spec.rb +36 -0
  138. data/spec/unit/middleware/authentication/password_spec.rb +31 -0
  139. data/spec/unit/middleware/authentication/token_spec.rb +24 -0
  140. data/spec/unit/middleware/authentication_spec.rb +67 -0
  141. data/spec/unit/middleware/authorization_spec.rb +11 -0
  142. data/spec/unit/middleware/gzip_spec.rb +66 -0
  143. data/spec/unit/middleware/instance_url_spec.rb +24 -0
  144. data/spec/unit/middleware/logger_spec.rb +19 -0
  145. data/spec/unit/middleware/mashify_spec.rb +11 -0
  146. data/spec/unit/middleware/raise_error_spec.rb +32 -0
  147. data/spec/unit/signed_request_spec.rb +24 -0
  148. data/spec/unit/sobject_spec.rb +86 -0
  149. data/spec/unit/tooling/client_spec.rb +7 -0
  150. data/tmp/rspec_guard_result +1 -0
  151. metadata +383 -0
@@ -0,0 +1,39 @@
1
+ module Force
2
+ module Concerns
3
+ module Authentication
4
+
5
+ # Public: Force an authentication
6
+ def authenticate!
7
+ raise AuthenticationError, 'No authentication middleware present' unless authentication_middleware
8
+ middleware = authentication_middleware.new nil, self, options
9
+ middleware.authenticate!
10
+ end
11
+
12
+ # Internal: Determines what middleware will be used based on the options provided
13
+ def authentication_middleware
14
+ if username_password?
15
+ Force::Middleware::Authentication::Password
16
+ elsif oauth_refresh?
17
+ Force::Middleware::Authentication::Token
18
+ end
19
+ end
20
+
21
+ # Internal: Returns true if username/password (autonomous) flow should be used for
22
+ # authentication.
23
+ def username_password?
24
+ options[:username] &&
25
+ options[:password] &&
26
+ options[:client_id] &&
27
+ options[:client_secret]
28
+ end
29
+
30
+ # Internal: Returns true if oauth token refresh flow should be used for
31
+ # authentication.
32
+ def oauth_refresh?
33
+ options[:refresh_token] &&
34
+ options[:client_id] &&
35
+ options[:client_secret]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,59 @@
1
+ module Force
2
+ module Concerns
3
+ module Base
4
+ attr_reader :options
5
+
6
+ # Public: Creates a new client instance
7
+ #
8
+ # options - A hash of options to be passed in (default: {}).
9
+ # :username - The String username to use (required for password authentication).
10
+ # :password - The String password to use (required for password authentication).
11
+ # :security_token - The String security token to use (required for password authentication).
12
+ #
13
+ # :oauth_token - The String oauth access token to authenticate api
14
+ # calls (required unless password
15
+ # authentication is used).
16
+ # :refresh_token - The String refresh token to obtain fresh
17
+ # oauth access tokens (required if oauth
18
+ # authentication is used).
19
+ # :instance_url - The String base url for all api requests
20
+ # (required if oauth authentication is used).
21
+ #
22
+ # :client_id - The oauth client id to use. Needed for both
23
+ # password and oauth authentication
24
+ # :client_secret - The oauth client secret to use.
25
+ #
26
+ # :host - The String hostname to use during
27
+ # authentication requests (default: 'login.salesforce.com').
28
+ #
29
+ # :api_version - The String REST api version to use (default: '24.0')
30
+ #
31
+ # :authentication_retries - The number of times that client
32
+ # should attempt to reauthenticate
33
+ # before raising an exception (default: 3).
34
+ #
35
+ # :compress - Set to true to have Salesforce compress the response (default: false).
36
+ # :timeout - Faraday connection request read/open timeout. (default: nil).
37
+ #
38
+ # :proxy_uri - Proxy URI: 'http://proxy.example.com:port' or 'http://user@pass:proxy.example.com:port'
39
+ #
40
+ # :authentication_callback
41
+ # - A Proc that is called with the response body after a successful authentication.
42
+ def initialize(options = {})
43
+ @options = Hash[Force.configuration.options.map { |option| [option, Force.configuration.send(option)] }]
44
+ @options.merge!(options)
45
+
46
+ yield builder if block_given?
47
+ end
48
+
49
+ def instance_url
50
+ authenticate! unless options[:instance_url]
51
+ options[:instance_url]
52
+ end
53
+
54
+ def inspect
55
+ "#<#{self.class} @options=#{@options.inspect}>"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,24 @@
1
+ module Force
2
+ module Concerns
3
+ module Caching
4
+ # Public: Runs the block with caching disabled.
5
+ #
6
+ # block - A query/describe/etc.
7
+ #
8
+ # Returns the result of the block
9
+ def without_caching(&block)
10
+ options[:use_cache] = false
11
+ block.call
12
+ ensure
13
+ options.delete(:use_cache)
14
+ end
15
+
16
+ private
17
+
18
+ # Internal: Cache to use for the caching middleware
19
+ def cache
20
+ options[:cache]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module Force
2
+ module Concerns
3
+ module Canvas
4
+ def decode_signed_request(signed_request)
5
+ raise 'client_secret not set.' unless options[:client_secret]
6
+ SignedRequest.decode(signed_request, options[:client_secret])
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,74 @@
1
+ module Force
2
+ module Concerns
3
+ module Connection
4
+ # Public: The Faraday::Builder instance used for the middleware stack. This
5
+ # can be used to insert an custom middleware.
6
+ #
7
+ # Examples
8
+ #
9
+ # # Add the instrumentation middleware for Rails.
10
+ # client.middleware.use FaradayMiddleware::Instrumentation
11
+ #
12
+ # Returns the Faraday::Builder for the Faraday connection.
13
+ def middleware
14
+ connection.builder
15
+ end
16
+
17
+ alias_method :builder, :middleware
18
+
19
+ private
20
+
21
+ # Internal: Internal faraday connection where all requests go through
22
+ def connection
23
+ @connection ||= Faraday.new(options[:instance_url], connection_options) do |builder|
24
+ # Parses JSON into Hashie::Mash structures.
25
+ builder.use Force::Middleware::Mashify, self, options
26
+ # Handles multipart file uploads for blobs.
27
+ builder.use Force::Middleware::Multipart
28
+ # Converts the request into JSON.
29
+ builder.request :json
30
+ # Handles reauthentication for 403 responses.
31
+ builder.use authentication_middleware, self, options if authentication_middleware
32
+ # Sets the oauth token in the headers.
33
+ builder.use Force::Middleware::Authorization, self, options
34
+ # Ensures the instance url is set.
35
+ builder.use Force::Middleware::InstanceURL, self, options
36
+ # Parses returned JSON response into a hash.
37
+ builder.response :json, :content_type => /\bjson$/
38
+ # Caches GET requests.
39
+ builder.use Force::Middleware::Caching, cache, options if cache
40
+ # Follows 30x redirects.
41
+ builder.use FaradayMiddleware::FollowRedirects
42
+ # Raises errors for 40x responses.
43
+ builder.use Force::Middleware::RaiseError
44
+ # Log request/responses
45
+ builder.use Force::Middleware::Logger, Force.configuration.logger, options if Force.log?
46
+ # Compress/Decompress the request/response
47
+ builder.use Force::Middleware::Gzip, self, options
48
+
49
+ builder.adapter adapter
50
+ end
51
+ end
52
+
53
+ def adapter
54
+ options[:adapter]
55
+ end
56
+
57
+ # Internal: Faraday Connection options
58
+ def connection_options
59
+ { :request => {
60
+ :timeout => options[:timeout],
61
+ :open_timeout => options[:timeout] },
62
+ :proxy => options[:proxy_uri],
63
+ :ssl => {:verify => false}
64
+ }
65
+ end
66
+
67
+ # Internal: Returns true if the middlware stack includes the
68
+ # Force::Middleware::Mashify middleware.
69
+ def mashify?
70
+ middleware.handlers.index(Force::Middleware::Mashify)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,87 @@
1
+ module Force
2
+ module Concerns
3
+ module Picklists
4
+ # Public: Get the available picklist values for a picklist or multipicklist field.
5
+ #
6
+ # sobject - The String name of the sobject.
7
+ # field - The String name of the picklist/multipicklist field.
8
+ # options - A hash of options. (default: {}).
9
+ # :valid_for - If specified, will only return picklist values
10
+ # that are valid for the controlling picklist
11
+ # value
12
+ #
13
+ # Examples
14
+ #
15
+ # client.picklist_values('Account', 'Type')
16
+ # # => [#<Force::Mash label="Prospect" value="Prospect">]
17
+ #
18
+ # # Given a custom object named Automobile__c with picklist fields
19
+ # # Model__c and Make__c, where Model__c depends on the value of
20
+ # # Make__c.
21
+ # client.picklist_values('Automobile__c', 'Model__c', :valid_for => 'Honda')
22
+ # # => [#<Force::Mash label="Civic" value="Civic">, ... ]
23
+ #
24
+ # Returns an array of Force::Mash objects.
25
+ def picklist_values(sobject, field, options = {})
26
+ PicklistValues.new(describe(sobject)['fields'], field, options)
27
+ end
28
+
29
+ private
30
+
31
+ class PicklistValues < Array
32
+
33
+ def initialize(fields, field, options = {})
34
+ @fields, @field = fields, field
35
+ @valid_for = options.delete(:valid_for)
36
+ raise "#{field} is not a dependent picklist" if @valid_for && !dependent?
37
+ replace(picklist_values)
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :fields
43
+
44
+ def picklist_values
45
+ if valid_for?
46
+ field['picklistValues'].select { |picklist_entry| valid? picklist_entry }
47
+ else
48
+ field['picklistValues']
49
+ end
50
+ end
51
+
52
+ # Returns true of the given field is dependent on another field.
53
+ def dependent?
54
+ !!field['dependentPicklist']
55
+ end
56
+
57
+ def valid_for?
58
+ !!@valid_for
59
+ end
60
+
61
+ def controlling_picklist
62
+ @_controlling_picklist ||= controlling_field['picklistValues'].find { |picklist_entry| picklist_entry['value'] == @valid_for }
63
+ end
64
+
65
+ def index
66
+ @_index ||= controlling_field['picklistValues'].index(controlling_picklist)
67
+ end
68
+
69
+ def controlling_field
70
+ @_controlling_field ||= fields.find { |f| f['name'] == field['controllerName'] }
71
+ end
72
+
73
+ def field
74
+ @_field ||= fields.find { |f| f['name'] == @field }
75
+ end
76
+
77
+ # Returns true if the picklist entry is valid for the controlling picklist.
78
+ #
79
+ # See http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_describesobjects_describesobjectresult.htm
80
+ def valid?(picklist_entry)
81
+ valid_for = picklist_entry['validFor'].ljust(16, 'A').unpack('m').first.unpack('q*')
82
+ (valid_for[index >> 3] & (0x80 >> index % 8)) != 0
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,31 @@
1
+ module Force
2
+ module Concerns
3
+ module Streaming
4
+ # Public: Subscribe to a PushTopic
5
+ #
6
+ # channels - The name of the PushTopic channel(s) to subscribe to.
7
+ # block - A block to run when a new message is received.
8
+ #
9
+ # Returns a Faye::Subscription
10
+ def subscribe(channels, &block)
11
+ faye.subscribe Array(channels).map { |channel| "/topic/#{channel}" }, &block
12
+ end
13
+
14
+ # Public: Faye client to use for subscribing to PushTopics
15
+ def faye
16
+ raise 'Instance URL missing. Call .authenticate! first.' unless options[:instance_url]
17
+
18
+ @faye ||= Faye::Client.new("#{options[:instance_url]}/cometd/#{options[:api_version]}").tap do |client|
19
+ client.bind 'transport:down' do
20
+ Force.log "[COMETD DOWN]"
21
+ client.set_header 'Authorization', "OAuth #{authenticate!.access_token}"
22
+ end
23
+
24
+ client.bind 'transport:up' do
25
+ Force.log "[COMETD UP]"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ module Force
2
+ module Concerns
3
+ module Verbs
4
+ # Internal: Define methods to handle a verb.
5
+ #
6
+ # verbs - A list of verbs to define methods for.
7
+ #
8
+ # Examples
9
+ #
10
+ # define_verbs :get, :post
11
+ #
12
+ # Returns nil.
13
+ def define_verbs(*verbs)
14
+ verbs.each do |verb|
15
+ define_verb(verb)
16
+ define_api_verb(verb)
17
+ end
18
+ end
19
+
20
+ # Internal: Defines a method to handle HTTP requests with the passed in
21
+ # verb.
22
+ #
23
+ # verb - Symbol name of the verb (e.g. :get).
24
+ #
25
+ # Examples
26
+ #
27
+ # define_verb :get
28
+ # # => get '/services/data/v24.0/sobjects'
29
+ #
30
+ # Returns nil.
31
+ def define_verb(verb)
32
+ define_method verb do |*args, &block|
33
+ retries = options[:authentication_retries]
34
+ begin
35
+ connection.send(verb, *args, &block)
36
+ rescue Force::UnauthorizedError
37
+ if retries > 0
38
+ retries -= 1
39
+ connection.url_prefix = options[:instance_url]
40
+ retry
41
+ end
42
+
43
+ raise
44
+ end
45
+ end
46
+ end
47
+
48
+ # Internal: Defines a method to handle HTTP requests with the passed in
49
+ # verb to a salesforce api endpoint.
50
+ #
51
+ # verb - Symbol name of the verb (e.g. :get).
52
+ #
53
+ # Examples
54
+ #
55
+ # define_api_verb :get
56
+ # # => api_get 'sobjects'
57
+ #
58
+ # Returns nil.
59
+ def define_api_verb(verb)
60
+ define_method :"api_#{verb}" do |*args, &block|
61
+ args[0] = api_path(args[0])
62
+ send(verb, *args, &block)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,140 @@
1
+ require 'logger'
2
+
3
+ module Force
4
+ class << self
5
+ attr_writer :log
6
+
7
+ # Returns the current Configuration
8
+ #
9
+ # Example
10
+ #
11
+ # Force.configuration.username = "username"
12
+ # Force.configuration.password = "password"
13
+ def configuration
14
+ @configuration ||= Configuration.new
15
+ end
16
+
17
+ # Yields the Configuration
18
+ #
19
+ # Example
20
+ #
21
+ # Force.configure do |config|
22
+ # config.username = "username"
23
+ # config.password = "password"
24
+ # end
25
+ def configure
26
+ yield configuration
27
+ end
28
+
29
+ def log?
30
+ @log ||= false
31
+ end
32
+
33
+ def log(message)
34
+ return unless Force.log?
35
+ Force.configuration.logger.send :debug, message
36
+ end
37
+ end
38
+
39
+ class Configuration
40
+ class Option
41
+ attr_reader :configuration, :name, :options
42
+
43
+ def self.define(*args)
44
+ new(*args).define
45
+ end
46
+
47
+ def initialize(configuration, name, options = {})
48
+ @configuration, @name, @options = configuration, name, options
49
+ @default = options.fetch(:default, nil)
50
+ end
51
+
52
+ def define
53
+ write_attribute
54
+ define_method if default_provided?
55
+ self
56
+ end
57
+
58
+ private
59
+
60
+ attr_reader :default
61
+ alias_method :default_provided?, :default
62
+
63
+ def write_attribute
64
+ configuration.send :attr_accessor, name
65
+ end
66
+
67
+ def define_method
68
+ our_default = default
69
+ our_name = name
70
+ configuration.send :define_method, our_name do
71
+ instance_variable_get(:"@#{our_name}") ||
72
+ instance_variable_set(:"@#{our_name}", our_default.respond_to?(:call) ? our_default.call : our_default)
73
+ end
74
+ end
75
+ end
76
+
77
+ class << self
78
+ attr_accessor :options
79
+
80
+ def option(*args)
81
+ option = Option.define(self, *args)
82
+ (self.options ||= []) << option.name
83
+ end
84
+ end
85
+
86
+ option :api_version, :default => '26.0'
87
+
88
+ # The username to use during login.
89
+ option :username, :default => lambda { ENV['SALESFORCE_USERNAME'] }
90
+
91
+ # The password to use during login.
92
+ option :password, :default => lambda { ENV['SALESFORCE_PASSWORD'] }
93
+
94
+ # The security token to use during login.
95
+ option :security_token, :default => lambda { ENV['SALESFORCE_SECURITY_TOKEN'] }
96
+
97
+ # The OAuth client id
98
+ option :client_id, :default => lambda { ENV['SALESFORCE_CLIENT_ID'] }
99
+
100
+ # The OAuth client secret
101
+ option :client_secret, :default => lambda { ENV['SALESFORCE_CLIENT_SECRET'] }
102
+
103
+ # Set this to true if you're authenticating with a Sandbox instance.
104
+ # Defaults to false.
105
+ option :host, :default => lambda { ENV['SALESFORCE_HOST'] || 'login.salesforce.com' }
106
+
107
+ option :oauth_token
108
+ option :refresh_token
109
+ option :instance_url
110
+
111
+ # Set this to an object that responds to read, write and fetch and all GET
112
+ # requests will be cached.
113
+ option :cache
114
+
115
+ # The number of times reauthentication should be tried before failing.
116
+ option :authentication_retries, :default => 3
117
+
118
+ # Set to true if you want responses from Salesforce to be gzip compressed.
119
+ option :compress
120
+
121
+ # Faraday request read/open timeout.
122
+ option :timeout
123
+
124
+ # Faraday adapter to use. Defaults to Faraday.default_adapter.
125
+ option :adapter, :default => lambda { Faraday.default_adapter }
126
+
127
+ option :proxy_uri, :default => lambda { ENV['PROXY_URI'] }
128
+
129
+ # A Proc that is called with the response body after a successful authentication.
130
+ option :authentication_callback
131
+
132
+ def logger
133
+ @logger ||= ::Logger.new STDOUT
134
+ end
135
+
136
+ def options
137
+ self.class.options
138
+ end
139
+ end
140
+ end