spark_api 1.3.16 → 1.3.17

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -21,6 +21,7 @@ Usage Examples
21
21
  ------------------------
22
22
 
23
23
  ```ruby
24
+ require 'spark_api'
24
25
  SparkApi.configure do |config|
25
26
  config.endpoint = 'https://sparkapi.com'
26
27
  # Using Spark API Authentication, refer to the Authentication documentation for OAuth2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.16
1
+ 1.3.17
@@ -29,6 +29,10 @@ module SparkApi
29
29
  end
30
30
  @logger
31
31
  end
32
+
33
+ def self.logger= logger
34
+ @logger = logger
35
+ end
32
36
  #:nocov:
33
37
 
34
38
  def self.client(opts={})
@@ -22,8 +22,8 @@ module SparkApi
22
22
  start_time = Time.now
23
23
  request_time = Time.now - start_time
24
24
  new_session = @authenticator.authenticate
25
- SparkApi.logger.info("[#{(request_time * 1000).to_i}ms]")
26
- SparkApi.logger.debug("Session: #{new_session.inspect}")
25
+ SparkApi.logger.info { "[#{(request_time * 1000).to_i}ms]" }
26
+ SparkApi.logger.debug { "Session: #{new_session.inspect}" }
27
27
  new_session
28
28
  end
29
29
 
@@ -34,7 +34,7 @@ module SparkApi
34
34
 
35
35
  # Delete the current session
36
36
  def logout
37
- SparkApi.logger.info("Logging out.")
37
+ SparkApi.logger.info { "Logging out." }
38
38
  @authenticator.logout
39
39
  end
40
40
 
@@ -17,15 +17,15 @@ module SparkApi
17
17
 
18
18
  def authenticate
19
19
  sig = sign("#{@client.api_secret}ApiKey#{@client.api_key}")
20
- SparkApi.logger.debug("Authenticating to #{@client.endpoint}")
20
+ SparkApi.logger.debug { "Authenticating to #{@client.endpoint}" }
21
21
  start_time = Time.now
22
22
  request_path = "/#{@client.version}/session?ApiKey=#{@client.api_key}&ApiSig=#{sig}"
23
23
  resp = @client.connection(true).post request_path, ""
24
24
  request_time = Time.now - start_time
25
- SparkApi.logger.info("[#{(request_time * 1000).to_i}ms] Api: POST #{request_path}")
26
- SparkApi.logger.debug("Authentication Response: #{resp.inspect}")
25
+ SparkApi.logger.info { "[#{(request_time * 1000).to_i}ms] Api: POST #{request_path}" }
26
+ SparkApi.logger.debug { "Authentication Response: #{resp.inspect}" }
27
27
  @session = Session.new(resp.body.results.first)
28
- SparkApi.logger.debug("Authentication: #{@session.inspect}")
28
+ SparkApi.logger.debug { "Authentication: #{@session.inspect}" }
29
29
  @session
30
30
  end
31
31
 
@@ -74,11 +74,11 @@ module SparkApi
74
74
  request_opts.merge!(options)
75
75
  sig = sign_token(escaped_path, request_opts, body)
76
76
  request_path = "#{escaped_path}?#{build_url_parameters({"ApiSig"=>sig}.merge(request_opts))}"
77
- SparkApi.logger.debug("Request: #{request_path}")
77
+ SparkApi.logger.debug { "Request: #{request_path}" }
78
78
  if body.nil?
79
79
  response = @client.connection.send(method, request_path)
80
80
  else
81
- SparkApi.logger.debug("Data: #{body}")
81
+ SparkApi.logger.debug { "Data: #{body}" }
82
82
  response = @client.connection.send(method, request_path, body)
83
83
  end
84
84
  response
@@ -50,11 +50,11 @@ module SparkApi
50
50
 
51
51
  parameter_string = options.size > 0 ? "?#{build_url_parameters(options)}" : ""
52
52
  request_path = "#{escaped_path}#{parameter_string}"
53
- SparkApi.logger.debug("Request: #{request_path}")
53
+ SparkApi.logger.debug { "Request: #{request_path}" }
54
54
  if body.nil?
55
55
  response = connection.send(method, request_path)
56
56
  else
57
- SparkApi.logger.debug("Data: #{body}")
57
+ SparkApi.logger.debug { "Data: #{body}" }
58
58
  response = connection.send(method, request_path, body)
59
59
  end
60
60
  response
@@ -76,14 +76,14 @@ module SparkApi
76
76
  # Create a sparkbar token based on the current user's access token
77
77
  def sparkbar_token()
78
78
  raise ClientError, "OAuth2Provider must configure the sparkbar_uri to use sparkbar tokens" if provider.sparkbar_uri.nil?
79
- SparkApi.logger.debug("[sparkbar] create token to #{provider.sparkbar_uri}")
79
+ SparkApi.logger.debug { "[sparkbar] create token to #{provider.sparkbar_uri}" }
80
80
  uri = URI.parse(provider.sparkbar_uri)
81
81
  request_path = "#{uri.path}"
82
82
 
83
- SparkApi.logger.info("[sparkbar] create token to #{request_path}, #{session.access_token.inspect}")
83
+ SparkApi.logger.info { "[sparkbar] create token to #{request_path}, #{session.access_token.inspect}" }
84
84
  response = sparkbar_connection("#{uri.scheme}://#{uri.host}").post(request_path, "access_token=#{session.access_token}").body
85
85
  token = response["token"]
86
- SparkApi.logger.debug("[sparkbar] New token created #{token}")
86
+ SparkApi.logger.debug { "[sparkbar] New token created #{token}" }
87
87
  token
88
88
  end
89
89
 
@@ -14,22 +14,22 @@ module SparkApi
14
14
 
15
15
  def on_complete(env)
16
16
  body = MultiJson.decode(env[:body])
17
- SparkApi.logger.debug("[oauth2] Response Body: #{body.inspect}")
17
+ SparkApi.logger.debug { "[oauth2] Response Body: #{body.inspect}" }
18
18
  unless body.is_a?(Hash)
19
19
  raise InvalidResponse, "The server response could not be understood"
20
20
  end
21
21
  case env[:status]
22
22
  when 200..299
23
- SparkApi.logger.debug("[oauth2] Success!")
23
+ SparkApi.logger.debug{ "[oauth2] Success!" }
24
24
  session = OAuthSession.new(body)
25
25
  else
26
26
  # Handle the WWW-Authenticate Response Header Field if present. This can be returned by
27
27
  # OAuth2 implementations and wouldn't hurt to log.
28
28
  auth_header_error = env[:request_headers]["WWW-Authenticate"]
29
- SparkApi.logger.warn("Authentication error #{auth_header_error}") unless auth_header_error.nil?
29
+ SparkApi.logger.warn { "Authentication error #{auth_header_error}" } unless auth_header_error.nil?
30
30
  raise ClientError, {:message => body["error"], :code =>0, :status => env[:status]}
31
31
  end
32
- SparkApi.logger.debug("[oauth2] Session=#{session.inspect}")
32
+ SparkApi.logger.debug { "[oauth2] Session=#{session.inspect}" }
33
33
  env[:body] = session
34
34
  end
35
35
 
@@ -46,13 +46,13 @@ module SparkApi
46
46
 
47
47
  def on_complete(env)
48
48
  body = MultiJson.decode(env[:body])
49
- SparkApi.logger.debug("[sparkbar] Response Body: #{body.inspect}")
49
+ SparkApi.logger.debug{ "[sparkbar] Response Body: #{body.inspect}" }
50
50
  unless body.is_a?(Hash)
51
51
  raise InvalidResponse, "The server response could not be understood"
52
52
  end
53
53
  case env[:status]
54
54
  when 200..299
55
- SparkApi.logger.debug("[sparkbar] Success!")
55
+ SparkApi.logger.debug{ "[sparkbar] Success!" }
56
56
  if body.include?("token")
57
57
  env[:body] = body
58
58
  return
@@ -17,7 +17,7 @@ module SparkApi
17
17
  else
18
18
  raise ClientError, "Unsupported grant type [#{provider.grant_type}]"
19
19
  end
20
- SparkApi.logger.debug("[oauth2] setup #{granter.class.name}")
20
+ SparkApi.logger.debug { "[oauth2] setup #{granter.class.name}" }
21
21
  granter
22
22
  end
23
23
 
@@ -38,16 +38,16 @@ module SparkApi
38
38
  protected
39
39
 
40
40
  def create_session(token_params)
41
- SparkApi.logger.debug("[oauth2] create_session to #{provider.access_uri} params #{token_params}")
41
+ SparkApi.logger.debug { "[oauth2] create_session to #{provider.access_uri} params #{token_params}" }
42
42
  uri = URI.parse(provider.access_uri)
43
43
  request_path = "#{uri.path}"
44
44
  response = oauth_access_connection("#{uri.scheme}://#{uri.host}").post(request_path, "#{token_params}").body
45
45
  response.expires_in = provider.session_timeout if response.expires_in.nil?
46
- SparkApi.logger.debug("[oauth2] New session created #{response}")
46
+ SparkApi.logger.debug { "[oauth2] New session created #{response}" }
47
47
  response
48
48
  rescue Faraday::Error::ConnectionFailed => e
49
49
  if @client.ssl_verify && e.message =~ /certificate verify failed/
50
- SparkApi.logger.error(SparkApi::Errors.ssl_verification_error)
50
+ SparkApi.logger.error { SparkApi::Errors.ssl_verification_error }
51
51
  end
52
52
  raise e
53
53
  end
@@ -10,7 +10,7 @@ module SparkApi
10
10
  end
11
11
  def authenticate
12
12
  if(provider.code.nil?)
13
- SparkApi.logger.debug("[oauth2] No authoriztion code present. Redirecting to #{authorization_url}.")
13
+ SparkApi.logger.debug { "[oauth2] No authoriztion code present. Redirecting to #{authorization_url}." }
14
14
  provider.redirect(authorization_url)
15
15
  end
16
16
  if needs_refreshing?
@@ -21,12 +21,12 @@ module SparkApi
21
21
  end
22
22
 
23
23
  def refresh()
24
- SparkApi.logger.debug("[oauth2] Refresh oauth session.")
24
+ SparkApi.logger.debug { "[oauth2] Refresh oauth session." }
25
25
  refresher = GrantTypeRefresh.new(client,provider,session)
26
26
  refresher.params = {"redirect_uri" => @provider.redirect_uri}
27
27
  refresher.authenticate
28
28
  rescue ClientError => e
29
- SparkApi.logger.info("[oauth2] Refreshing token failed, the library will try and authenticate from scratch: #{e.message}")
29
+ SparkApi.logger.info { "[oauth2] Refreshing token failed, the library will try and authenticate from scratch: #{e.message}" }
30
30
  nil
31
31
  end
32
32
 
@@ -12,7 +12,7 @@ module SparkApi
12
12
  def authenticate
13
13
  new_session = nil
14
14
  unless @session.refresh_token.nil?
15
- SparkApi.logger.debug("[oauth2] Refreshing authentication to #{provider.access_uri} using [#{session.refresh_token}]")
15
+ SparkApi.logger.debug { "[oauth2] Refreshing authentication to #{provider.access_uri} using [#{session.refresh_token}]" }
16
16
  new_session = create_session(token_params)
17
17
  end
18
18
  new_session
@@ -27,7 +27,7 @@ module SparkApi
27
27
  conn.options[:timeout] = self.timeout
28
28
  conn.adapter Faraday.default_adapter
29
29
  end
30
- SparkApi.logger.debug("Connection: #{conn.inspect}")
30
+ SparkApi.logger.debug { "Connection: #{conn.inspect}" }
31
31
  conn
32
32
  end
33
33
 
@@ -19,7 +19,7 @@ module SparkApi
19
19
  env[:body] = decompress_body(env)
20
20
 
21
21
  body = MultiJson.decode(env[:body])
22
- SparkApi.logger.debug("Response Body: #{body.inspect}")
22
+ SparkApi.logger.debug{ "Response Body: #{body.inspect}" }
23
23
  unless body.is_a?(Hash) && body.key?("D")
24
24
  raise InvalidResponse, "The server response could not be understood"
25
25
  end
@@ -60,7 +60,7 @@ module SparkApi
60
60
  when 500
61
61
  raise ClientError, {:message => response.message, :code => response.code, :status => env[:status]}
62
62
  when 200..299
63
- SparkApi.logger.debug("Success!")
63
+ SparkApi.logger.debug { "Success!" }
64
64
  else
65
65
  raise ClientError, {:message => response.message, :code => response.code, :status => env[:status]}
66
66
  end
@@ -111,7 +111,6 @@ module SparkApi
111
111
  Note.build_subclass.tap do |note|
112
112
  note.prefix = "/listings/#{self.ListingKey}"
113
113
  note.element_name = "/my/notes"
114
- SparkApi.logger.info("Note.path: #{note.path}")
115
114
  end
116
115
  end
117
116
 
@@ -148,7 +147,6 @@ module SparkApi
148
147
  return save!(arguments)
149
148
  rescue BadResourceRequest => e
150
149
  self.errors << {:code => e.code, :message => e.message}
151
- SparkApi.logger.debug("BHDEBUG: #{e.inspect}")
152
150
  if e.code == 1053
153
151
  @constraints = []
154
152
  e.details.each do |detail|
@@ -157,16 +155,16 @@ module SparkApi
157
155
  end
158
156
  end
159
157
  end
160
- SparkApi.logger.warn("Failed to save resource #{self}: #{e.message}")
158
+ SparkApi.logger.warn { "Failed to save resource #{self}: #{e.message}" }
161
159
  rescue NotFound => e
162
- SparkApi.logger.error("Failed to save resource #{self}: #{e.message}")
160
+ SparkApi.logger.error { "Failed to save resource #{self}: #{e.message}" }
163
161
  end
164
162
  false
165
163
  end
166
164
  def save!(arguments={})
167
165
  writable_changed_keys = changed & WRITEABLE_FIELDS
168
166
  if writable_changed_keys.empty?
169
- SparkApi.logger.warn("No supported listing change detected")
167
+ SparkApi.logger.warn { "No supported listing change detected" }
170
168
  else
171
169
  results = connection.put "#{self.class.path}/#{self.Id}", build_hash(writable_changed_keys), arguments
172
170
  @contstraints = []
@@ -183,9 +181,9 @@ module SparkApi
183
181
  begin
184
182
  return reorder_photos!(arguments)
185
183
  rescue BadResourceRequest => e
186
- SparkApi.logger.warn("Failed to save resource #{self}: #{e.message}")
184
+ SparkApi.logger.warn { "Failed to save resource #{self}: #{e.message}" }
187
185
  rescue NotFound => e
188
- SparkApi.logger.error("Failed to save resource #{self}: #{e.message}")
186
+ SparkApi.logger.error { "Failed to save resource #{self}: #{e.message}" }
189
187
  end
190
188
  false
191
189
  end
@@ -209,7 +207,14 @@ module SparkApi
209
207
  def ExpirationDate=(value)
210
208
  write_attribute("ExpirationDate", value)
211
209
  end
212
-
210
+
211
+ def respond_to?(method_symbol, include_all=false)
212
+ if super
213
+ true
214
+ else
215
+ attributes['StandardFields'].include?(method_symbol.to_s) rescue false
216
+ end
217
+ end
213
218
 
214
219
  private
215
220
 
@@ -13,10 +13,10 @@ module SparkApi
13
13
  end
14
14
 
15
15
  def ListingIds=(listing_ids)
16
- attributes["ListingIds"] = Array(listing_ids)
16
+ write_attribute("ListingIds", Array(listing_ids))
17
17
  end
18
18
  def Name=(name)
19
- attributes["Name"] = name
19
+ write_attribute("Name", name)
20
20
  end
21
21
 
22
22
  def path
@@ -43,7 +43,7 @@ module SparkApi
43
43
  end
44
44
 
45
45
  def activate_client_from_config(symbol)
46
- SparkApi.logger.debug("Loading multiclient [#{symbol.to_s}] from config")
46
+ SparkApi.logger.debug { "Loading multiclient [#{symbol.to_s}] from config" }
47
47
  yaml = YamlConfig.build(symbol.to_s)
48
48
  if(yaml.oauth2?)
49
49
  Client.new(yaml.client_keys.merge({
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
  require 'cgi'
2
3
 
3
4
  module SparkApi
@@ -70,27 +71,27 @@ module SparkApi
70
71
  response = authenticator.request(method, request_path, nil, request_opts)
71
72
  else
72
73
  post_data = process_request_body(body)
73
- SparkApi.logger.debug("#{method.to_s.upcase} Data: #{post_data}")
74
+ SparkApi.logger.debug { "#{method.to_s.upcase} Data: #{post_data}" }
74
75
  response = authenticator.request(method, request_path, post_data, request_opts)
75
76
  end
76
77
  request_time = Time.now - start_time
77
- SparkApi.logger.debug("[#{(request_time * 1000).to_i}ms] Api: #{method.to_s.upcase} #{request_path}")
78
+ SparkApi.logger.debug { "[#{(request_time * 1000).to_i}ms] Api: #{method.to_s.upcase} #{request_path}" }
78
79
  rescue PermissionDenied => e
79
80
  if(ResponseCodes::SESSION_TOKEN_EXPIRED == e.code)
80
81
  unless (attempts +=1) > 1
81
- SparkApi.logger.debug("Retrying authentication")
82
+ SparkApi.logger.debug { "Retrying authentication" }
82
83
  authenticate
83
84
  retry
84
85
  end
85
86
  end
86
87
  # No luck authenticating... KABOOM!
87
- SparkApi.logger.error("Authentication failed or server is sending us expired tokens, nothing we can do here.")
88
+ SparkApi.logger.error { "Authentication failed or server is sending us expired tokens, nothing we can do here." }
88
89
  raise
89
90
  end
90
91
  response.body
91
92
  rescue Faraday::Error::ConnectionFailed => e
92
93
  if self.ssl_verify && e.message =~ /certificate verify failed/
93
- SparkApi.logger.error(SparkApi::Errors.ssl_verification_error)
94
+ SparkApi.logger.error { SparkApi::Errors.ssl_verification_error }
94
95
  end
95
96
  raise e
96
97
  end
@@ -0,0 +1,9 @@
1
+ {
2
+ "D": {
3
+ "ListingIds": [
4
+ "20110112234857732941000000",
5
+ "20110302120238448431000000",
6
+ "20110510011212354751000000"
7
+ ]
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "D": {
3
+ "ListingIds": [
4
+ "20110112234857732941000000",
5
+ "20110302120238448431000000",
6
+ "20110510011212354751000000"
7
+ ]
8
+ }
9
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "Name": "My Cart's Name"
4
+ }
5
+ }
@@ -14,7 +14,6 @@ require 'spark_api'
14
14
 
15
15
  FileUtils.mkdir 'log' unless File.exists? 'log'
16
16
 
17
- # TODO, really we should change the library to support configuration without overriding
18
17
  module SparkApi
19
18
  def self.logger
20
19
  if @logger.nil?
@@ -43,14 +43,24 @@ describe ListingCart do
43
43
  resource.ListingCount.should eq(10)
44
44
  end
45
45
 
46
- on_put_it "should save a listing cart" do
46
+ on_put_it "should save a listing cart Name" do
47
47
  stub_api_get("/#{subject.class.element_name}", 'listing_carts/listing_cart.json')
48
48
  resource = subject.class.get.first
49
- stub_api_put("/#{subject.class.element_name}/#{resource.Id}", 'listing_carts/new.json', 'success.json')
49
+ stub_api_put("/#{subject.class.element_name}/#{resource.Id}", 'listing_carts/put_name.json', 'success.json')
50
50
  resource.Name = "My Cart's Name"
51
+ resource.changed?.should be(true)
52
+ resource.save.should be(true)
53
+ resource.ResourceUri.should eq("/v1/listingcarts/20100912153422758914000000")
54
+ end
55
+
56
+ on_put_it "should save a listing cart ListingIds" do
57
+ stub_api_get("/#{subject.class.element_name}", 'listing_carts/listing_cart.json')
58
+ resource = subject.class.get.first
59
+ stub_api_put("/#{subject.class.element_name}/#{resource.Id}", 'listing_carts/put_ids.json', 'success.json')
51
60
  resource.ListingIds = ['20110112234857732941000000',
52
61
  '20110302120238448431000000',
53
62
  '20110510011212354751000000']
63
+ resource.changed?.should be(true)
54
64
  resource.save.should be(true)
55
65
  resource.ResourceUri.should eq("/v1/listingcarts/20100912153422758914000000")
56
66
  end
@@ -97,6 +97,28 @@ describe Listing do
97
97
  it "should return full address" do
98
98
  @listing.full_address.should eq("100 Someone's St, Fargo, ND 55320")
99
99
  end
100
+
101
+ it "should provide shortcut methods to standard fields" do
102
+ @listing.StreetName.should eq("Someone's")
103
+ @listing.YearBuilt.should eq(nil)
104
+ @listing.BuildingAreaTotal.should eq("1321.0")
105
+ @listing.PublicRemarks.should eq(nil)
106
+ @listing.PostalCode.should eq("55320")
107
+ @listing.ListPrice.should eq("100000.0")
108
+ end
109
+
110
+ it "should report that it responds to shortcut methods to standard fields" do
111
+ @listing.should respond_to(:StreetName)
112
+ @listing.should respond_to(:YearBuilt)
113
+ @listing.should respond_to(:BuildingAreaTotal)
114
+ @listing.should respond_to(:PublicRemarks)
115
+ @listing.should respond_to(:PostalCode)
116
+ @listing.should respond_to(:ListPrice)
117
+
118
+ @listing.should_not respond_to(:BogusField)
119
+ @listing.StandardFields['BogusField'] = 'bogus'
120
+ @listing.should respond_to(:BogusField)
121
+ end
100
122
  end
101
123
 
102
124
  describe "class methods" do