sfdc 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +96 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +11 -0
  5. data/LICENSE +22 -0
  6. data/README.md +88 -98
  7. data/Rakefile +10 -0
  8. data/lib/sfdc.rb +1 -0
  9. data/lib/sfdc/abstract_client.rb +1 -1
  10. data/lib/sfdc/attachment.rb +0 -2
  11. data/lib/sfdc/concerns/api.rb +1 -2
  12. data/lib/sfdc/concerns/authentication.rb +1 -2
  13. data/lib/sfdc/concerns/base.rb +5 -7
  14. data/lib/sfdc/concerns/caching.rb +1 -3
  15. data/lib/sfdc/concerns/canvas.rb +0 -2
  16. data/lib/sfdc/concerns/connection.rb +2 -3
  17. data/lib/sfdc/concerns/picklists.rb +1 -4
  18. data/lib/sfdc/concerns/streaming.rb +2 -2
  19. data/lib/sfdc/concerns/verbs.rb +0 -2
  20. data/lib/sfdc/config.rb +1 -0
  21. data/lib/sfdc/middleware/authentication.rb +4 -2
  22. data/lib/sfdc/middleware/authentication/password.rb +2 -5
  23. data/lib/sfdc/middleware/authorization.rb +1 -5
  24. data/lib/sfdc/middleware/caching.rb +0 -2
  25. data/lib/sfdc/middleware/instance_url.rb +0 -4
  26. data/lib/sfdc/middleware/mashify.rb +1 -3
  27. data/lib/sfdc/middleware/multipart.rb +6 -4
  28. data/lib/sfdc/signed_request.rb +1 -1
  29. data/lib/sfdc/tooling/client.rb +4 -6
  30. data/lib/sfdc/version.rb +2 -2
  31. data/sfdc.gemspec +27 -0
  32. data/spec/fixtures/auth_error_response.json +4 -0
  33. data/spec/fixtures/auth_success_response.json +7 -0
  34. data/spec/fixtures/blob.jpg +0 -0
  35. data/spec/fixtures/expired_session_response.json +6 -0
  36. data/spec/fixtures/reauth_success_response.json +7 -0
  37. data/spec/fixtures/refresh_error_response.json +4 -0
  38. data/spec/fixtures/refresh_success_response.json +7 -0
  39. data/spec/fixtures/services_data_success_response.json +12 -0
  40. data/spec/fixtures/sobject/create_success_response.json +5 -0
  41. data/spec/fixtures/sobject/delete_error_response.json +1 -0
  42. data/spec/fixtures/sobject/describe_sobjects_success_response.json +31 -0
  43. data/spec/fixtures/sobject/list_sobjects_success_response.json +31 -0
  44. data/spec/fixtures/sobject/org_query_response.json +11 -0
  45. data/spec/fixtures/sobject/query_aggregate_success_response.json +23 -0
  46. data/spec/fixtures/sobject/query_empty_response.json +5 -0
  47. data/spec/fixtures/sobject/query_error_response.json +6 -0
  48. data/spec/fixtures/sobject/query_paginated_first_page_response.json +14 -0
  49. data/spec/fixtures/sobject/query_paginated_last_page_response.json +13 -0
  50. data/spec/fixtures/sobject/query_success_response.json +38 -0
  51. data/spec/fixtures/sobject/recent_success_response.json +18 -0
  52. data/spec/fixtures/sobject/search_error_response.json +6 -0
  53. data/spec/fixtures/sobject/search_success_response.json +16 -0
  54. data/spec/fixtures/sobject/sobject_describe_error_response.json +6 -0
  55. data/spec/fixtures/sobject/sobject_describe_success_response.json +1429 -0
  56. data/spec/fixtures/sobject/sobject_find_error_response.json +6 -0
  57. data/spec/fixtures/sobject/sobject_find_success_response.json +29 -0
  58. data/spec/fixtures/sobject/upsert_created_success_response.json +5 -0
  59. data/spec/fixtures/sobject/upsert_error_response.json +6 -0
  60. data/spec/fixtures/sobject/upsert_multiple_error_response.json +4 -0
  61. data/spec/fixtures/sobject/upsert_updated_success_response.json +0 -0
  62. data/spec/fixtures/sobject/write_error_response.json +6 -0
  63. data/spec/integration/abstract_client_spec.rb +306 -0
  64. data/spec/integration/data/client_spec.rb +90 -0
  65. data/spec/spec_helper.rb +20 -0
  66. data/spec/support/client_integration.rb +45 -0
  67. data/spec/support/concerns.rb +18 -0
  68. data/spec/support/event_machine.rb +14 -0
  69. data/spec/support/fixture_helpers.rb +45 -0
  70. data/spec/support/matchers.rb +11 -0
  71. data/spec/support/middleware.rb +76 -0
  72. data/spec/support/mock_cache.rb +13 -0
  73. data/spec/unit/abstract_client_spec.rb +11 -0
  74. data/spec/unit/attachment_spec.rb +15 -0
  75. data/spec/unit/collection_spec.rb +52 -0
  76. data/spec/unit/concerns/api_spec.rb +244 -0
  77. data/spec/unit/concerns/authentication_spec.rb +98 -0
  78. data/spec/unit/concerns/base_spec.rb +42 -0
  79. data/spec/unit/concerns/caching_spec.rb +29 -0
  80. data/spec/unit/concerns/canvas_spec.rb +30 -0
  81. data/spec/unit/concerns/connection_spec.rb +22 -0
  82. data/spec/unit/config_spec.rb +99 -0
  83. data/spec/unit/data/client_spec.rb +10 -0
  84. data/spec/unit/mash_spec.rb +36 -0
  85. data/spec/unit/middleware/authentication/password_spec.rb +31 -0
  86. data/spec/unit/middleware/authentication/token_spec.rb +24 -0
  87. data/spec/unit/middleware/authentication_spec.rb +67 -0
  88. data/spec/unit/middleware/authorization_spec.rb +11 -0
  89. data/spec/unit/middleware/gzip_spec.rb +66 -0
  90. data/spec/unit/middleware/instance_url_spec.rb +24 -0
  91. data/spec/unit/middleware/logger_spec.rb +19 -0
  92. data/spec/unit/middleware/mashify_spec.rb +11 -0
  93. data/spec/unit/middleware/raise_error_spec.rb +32 -0
  94. data/spec/unit/signed_request_spec.rb +24 -0
  95. data/spec/unit/sobject_spec.rb +86 -0
  96. data/spec/unit/tooling/client_spec.rb +7 -0
  97. metadata +225 -65
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ task :default => [:spec]
5
+
6
+ require 'rspec/core/rake_task'
7
+ desc "Run specs"
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = 'spec/**/*_spec.rb'
10
+ end
@@ -69,5 +69,6 @@ module Sfdc
69
69
  self
70
70
  end
71
71
  end
72
+
72
73
  Object.send :include, Sfdc::CoreExtensions unless Object.respond_to? :tap
73
74
  end
@@ -6,4 +6,4 @@ module Sfdc
6
6
  include Sfdc::Concerns::Caching
7
7
  include Sfdc::Concerns::API
8
8
  end
9
- end
9
+ end
@@ -1,6 +1,5 @@
1
1
  module Sfdc
2
2
  class Attachment < Sfdc::SObject
3
-
4
3
  # Public: Returns the body of the attachment.
5
4
  #
6
5
  # Examples
@@ -18,6 +17,5 @@ module Sfdc
18
17
  return true if self.Body?
19
18
  raise 'You need to query the Body for the record first.'
20
19
  end
21
-
22
20
  end
23
21
  end
@@ -300,7 +300,7 @@ module Sfdc
300
300
  api_get(field ? "sobjects/#{sobject}/#{field}/#{id}" : "sobjects/#{sobject}/#{id}").body
301
301
  end
302
302
 
303
- private
303
+ private
304
304
 
305
305
  # Internal: Returns a path to an api endpoint
306
306
  #
@@ -316,7 +316,6 @@ module Sfdc
316
316
  def exceptions
317
317
  [Faraday::Error::ClientError]
318
318
  end
319
-
320
319
  end
321
320
  end
322
321
  end
@@ -2,7 +2,7 @@ module Sfdc
2
2
  module Concerns
3
3
  module Authentication
4
4
 
5
- # Public: Force an authentication
5
+ # Public: Sfdc an authentication
6
6
  def authenticate!
7
7
  raise AuthenticationError, 'No authentication middleware present' unless authentication_middleware
8
8
  middleware = authentication_middleware.new nil, self, options
@@ -34,7 +34,6 @@ module Sfdc
34
34
  options[:client_id] &&
35
35
  options[:client_secret]
36
36
  end
37
-
38
37
  end
39
38
  end
40
39
  end
@@ -1,12 +1,11 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Base
4
-
5
4
  attr_reader :options
6
5
 
7
6
  # Public: Creates a new client instance
8
7
  #
9
- # opts - A hash of options to be passed in (default: {}).
8
+ # options - A hash of options to be passed in (default: {}).
10
9
  # :username - The String username to use (required for password authentication).
11
10
  # :password - The String password to use (required for password authentication).
12
11
  # :security_token - The String security token to use (required for password authentication).
@@ -40,10 +39,10 @@ module Sfdc
40
39
  #
41
40
  # :authentication_callback
42
41
  # - A Proc that is called with the response body after a successful authentication.
43
- def initialize(opts = {})
44
- raise ArgumentError, 'Please specify a hash of options' unless opts.is_a?(Hash)
42
+ def initialize(options = {})
45
43
  @options = Hash[Sfdc.configuration.options.map { |option| [option, Sfdc.configuration.send(option)] }]
46
- @options.merge! opts
44
+ @options.merge!(options)
45
+
47
46
  yield builder if block_given?
48
47
  end
49
48
 
@@ -55,7 +54,6 @@ module Sfdc
55
54
  def inspect
56
55
  "#<#{self.class} @options=#{@options.inspect}>"
57
56
  end
58
-
59
57
  end
60
58
  end
61
- end
59
+ end
@@ -1,7 +1,6 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Caching
4
-
5
4
  # Public: Runs the block with caching disabled.
6
5
  #
7
6
  # block - A query/describe/etc.
@@ -14,13 +13,12 @@ module Sfdc
14
13
  options.delete(:use_cache)
15
14
  end
16
15
 
17
- private
16
+ private
18
17
 
19
18
  # Internal: Cache to use for the caching middleware
20
19
  def cache
21
20
  options[:cache]
22
21
  end
23
-
24
22
  end
25
23
  end
26
24
  end
@@ -1,12 +1,10 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Canvas
4
-
5
4
  def decode_signed_request(signed_request)
6
5
  raise 'client_secret not set.' unless options[:client_secret]
7
6
  SignedRequest.decode(signed_request, options[:client_secret])
8
7
  end
9
-
10
8
  end
11
9
  end
12
10
  end
@@ -1,7 +1,6 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Connection
4
-
5
4
  # Public: The Faraday::Builder instance used for the middleware stack. This
6
5
  # can be used to insert an custom middleware.
7
6
  #
@@ -14,9 +13,10 @@ module Sfdc
14
13
  def middleware
15
14
  connection.builder
16
15
  end
16
+
17
17
  alias_method :builder, :middleware
18
18
 
19
- private
19
+ private
20
20
 
21
21
  # Internal: Internal faraday connection where all requests go through
22
22
  def connection
@@ -68,7 +68,6 @@ module Sfdc
68
68
  def mashify?
69
69
  middleware.handlers.index(Sfdc::Middleware::Mashify)
70
70
  end
71
-
72
71
  end
73
72
  end
74
73
  end
@@ -1,7 +1,6 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Picklists
4
-
5
4
  # Public: Get the available picklist values for a picklist or multipicklist field.
6
5
  #
7
6
  # sobject - The String name of the sobject.
@@ -27,7 +26,7 @@ module Sfdc
27
26
  PicklistValues.new(describe(sobject)['fields'], field, options)
28
27
  end
29
28
 
30
- private
29
+ private
31
30
 
32
31
  class PicklistValues < Array
33
32
 
@@ -82,9 +81,7 @@ module Sfdc
82
81
  valid_for = picklist_entry['validFor'].ljust(16, 'A').unpack('m').first.unpack('q*')
83
82
  (valid_for[index >> 3] & (0x80 >> index % 8)) != 0
84
83
  end
85
-
86
84
  end
87
-
88
85
  end
89
86
  end
90
87
  end
@@ -1,7 +1,6 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Streaming
4
-
5
4
  # Public: Subscribe to a PushTopic
6
5
  #
7
6
  # channels - The name of the PushTopic channel(s) to subscribe to.
@@ -15,17 +14,18 @@ module Sfdc
15
14
  # Public: Faye client to use for subscribing to PushTopics
16
15
  def faye
17
16
  raise 'Instance URL missing. Call .authenticate! first.' unless options[:instance_url]
17
+
18
18
  @faye ||= Faye::Client.new("#{options[:instance_url]}/cometd/#{options[:api_version]}").tap do |client|
19
19
  client.bind 'transport:down' do
20
20
  Sfdc.log "[COMETD DOWN]"
21
21
  client.set_header 'Authorization', "OAuth #{authenticate!.access_token}"
22
22
  end
23
+
23
24
  client.bind 'transport:up' do
24
25
  Sfdc.log "[COMETD UP]"
25
26
  end
26
27
  end
27
28
  end
28
-
29
29
  end
30
30
  end
31
31
  end
@@ -1,7 +1,6 @@
1
1
  module Sfdc
2
2
  module Concerns
3
3
  module Verbs
4
-
5
4
  # Internal: Define methods to handle a verb.
6
5
  #
7
6
  # verbs - A list of verbs to define methods for.
@@ -62,7 +61,6 @@ module Sfdc
62
61
  send(verb, *args, &block)
63
62
  end
64
63
  end
65
-
66
64
  end
67
65
  end
68
66
  end
@@ -56,6 +56,7 @@ module Sfdc
56
56
  end
57
57
 
58
58
  private
59
+
59
60
  attr_reader :default
60
61
  alias_method :default_provided?, :default
61
62
 
@@ -62,10 +62,12 @@ module Sfdc
62
62
  end
63
63
  end
64
64
 
65
- private
65
+ private
66
+
66
67
  def faraday_options
67
68
  { :url => "https://#{@options[:host]}",
68
- :proxy => @options[:proxy_uri] }.reject { |k, v| v.nil? }
69
+ :proxy => @options[:proxy_uri]
70
+ }.reject { |k, v| v.nil? }
69
71
  end
70
72
  end
71
73
  end
@@ -1,20 +1,17 @@
1
1
  module Sfdc
2
-
3
2
  # Authentication middleware used if username and password flow is used
4
3
  class Middleware::Authentication::Password < Sfdc::Middleware::Authentication
5
-
6
4
  def params
7
5
  { :grant_type => 'password',
8
6
  :client_id => @options[:client_id],
9
7
  :client_secret => @options[:client_secret],
10
8
  :username => @options[:username],
11
- :password => password }
9
+ :password => password
10
+ }
12
11
  end
13
12
 
14
13
  def password
15
14
  "#{@options[:password]}#{@options[:security_token]}"
16
15
  end
17
-
18
16
  end
19
-
20
17
  end
@@ -1,7 +1,5 @@
1
1
  module Sfdc
2
-
3
- # Piece of middleware that simply injects the OAuth token into the request
4
- # headers.
2
+ # Middleware that simply injects the OAuth token into the request headers.
5
3
  class Middleware::Authorization < Sfdc::Middleware
6
4
  AUTH_HEADER = 'Authorization'.freeze
7
5
 
@@ -13,7 +11,5 @@ module Sfdc
13
11
  def token
14
12
  @options[:oauth_token]
15
13
  end
16
-
17
14
  end
18
-
19
15
  end
@@ -1,6 +1,5 @@
1
1
  module Sfdc
2
2
  class Middleware::Caching < FaradayMiddleware::Caching
3
-
4
3
  def call(env)
5
4
  expire(cache_key(env)) unless use_cache?
6
5
  super
@@ -19,6 +18,5 @@ module Sfdc
19
18
  def use_cache?
20
19
  !@options.has_key?(:use_cache) || @options[:use_cache]
21
20
  end
22
-
23
21
  end
24
22
  end
@@ -1,8 +1,6 @@
1
1
  module Sfdc
2
-
3
2
  # Middleware which asserts that the instance_url is always set
4
3
  class Middleware::InstanceURL < Sfdc::Middleware
5
-
6
4
  def call(env)
7
5
  # If the connection url_prefix isn't set, we must not be authenticated.
8
6
  raise Sfdc::UnauthorizedError, 'Connection prefix not set' unless url_prefix_set?
@@ -12,7 +10,5 @@ module Sfdc
12
10
  def url_prefix_set?
13
11
  !!(connection.url_prefix && connection.url_prefix.host)
14
12
  end
15
-
16
13
  end
17
-
18
14
  end
@@ -2,7 +2,6 @@ module Sfdc
2
2
  # Middleware the converts sobject records from JSON into Sfdc::SObject objects
3
3
  # and collections of records into Sfdc::Collection objects.
4
4
  class Middleware::Mashify < Sfdc::Middleware
5
-
6
5
  def call(env)
7
6
  @env = env
8
7
  response = @app.call(env)
@@ -12,7 +11,6 @@ module Sfdc
12
11
 
13
12
  def body
14
13
  @env[:body]
15
- end
16
-
14
+ end
17
15
  end
18
16
  end
@@ -10,7 +10,8 @@ module Sfdc
10
10
  env[:request_headers][CONTENT_TYPE] += ";boundary=#{env[:request][:boundary]}"
11
11
  env[:body] = create_multipart(env, params)
12
12
  end
13
- @app.call env
13
+
14
+ @app.call(env)
14
15
  end
15
16
 
16
17
  def process_request?(env)
@@ -28,17 +29,17 @@ module Sfdc
28
29
  return true if (val.respond_to?(:content_type) || has_multipart?(val))
29
30
  end
30
31
  end
31
- false
32
+
33
+ return false
32
34
  end
33
35
 
34
36
  def create_multipart(env, params)
35
37
  boundary = env[:request][:boundary]
38
+
36
39
  parts = []
37
40
 
38
- # Fields
39
41
  parts << Faraday::Parts::Part.new(boundary, 'entity_content', params.reject { |k,v| v.respond_to? :content_type }.to_json)
40
42
 
41
- # Files
42
43
  params.each do |k,v|
43
44
  parts << Faraday::Parts::Part.new(boundary, k.to_s, v) if v.respond_to? :content_type
44
45
  end
@@ -47,6 +48,7 @@ module Sfdc
47
48
 
48
49
  body = Faraday::CompositeReadIO.new(parts)
49
50
  env[:request_headers]['Content-Length'] = body.length.to_s
51
+
50
52
  return body
51
53
  end
52
54
  end
@@ -29,6 +29,7 @@ module Sfdc
29
29
  end
30
30
 
31
31
  private
32
+
32
33
  attr_reader :client_secret, :signature, :payload
33
34
 
34
35
  def split_components(signed_request)
@@ -43,6 +44,5 @@ module Sfdc
43
44
  def digest
44
45
  OpenSSL::Digest::Digest.new('sha256')
45
46
  end
46
-
47
47
  end
48
48
  end
@@ -1,13 +1,11 @@
1
1
  module Sfdc
2
2
  module Tooling
3
3
  class Client < AbstractClient
4
-
5
4
  private
6
5
 
7
- def api_path(path)
8
- super("tooling/#{path}")
9
- end
10
-
6
+ def api_path(path)
7
+ super("tooling/#{path}")
8
+ end
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module Sfdc
2
- VERSION = '3.0.0'
3
- end
2
+ VERSION = '3.0.1'
3
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/sfdc/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "sfdc"
6
+ s.version = Sfdc::VERSION
7
+ s.authors = ["Bruce Yue"]
8
+ s.email = ["bruce.yue@outlook.com"]
9
+ s.description = "A lightweight ruby client for the Salesforce REST api."
10
+ s.summary = "A lightweight ruby client for the Salesforce REST api."
11
+ s.homepage = "http://www.sharealltech.com"
12
+
13
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|example|log|pkg|script|spec|test|vendor)/ }
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency 'faraday', '~> 0.8.4'
19
+ s.add_dependency 'faraday_middleware', '>= 0.8.8'
20
+ s.add_dependency 'json', ['>= 1.7.5', '< 1.9.0']
21
+ s.add_dependency 'hashie', ['>= 1.2.0', '< 2.1']
22
+
23
+ s.add_development_dependency 'rspec', '~> 2.14.0'
24
+ s.add_development_dependency 'webmock', '~> 1.13.0'
25
+ s.add_development_dependency 'simplecov', '~> 0.7.1'
26
+ s.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
27
+ end