attune 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YmI0ZDQ2MjAxYWIyYzNiNDE0Y2E5YWI1YWFmMTUxMDcyYTNjZTc3Mw==
5
- data.tar.gz: !binary |-
6
- YmRkYWIzMTRhOGNlOTVlYzBhZDFjY2FkMGFkNDY2MGVlNWIzMGY2ZA==
2
+ SHA1:
3
+ metadata.gz: a768188791c5cf1b4dbb0d9bb7639c79be622f49
4
+ data.tar.gz: 0b55667d588255b97df0fc7fbc7d7571f2a3a420
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- M2UyY2E5ZTE5MzAyNGY2NGIzNjQyNDEwYWU0ZTRiN2FkYWEwNDA5MjY3Yjg2
10
- ZTQ3N2Q3ZGU3MzE0OWUzZWNiNmM2ZjUyMTQxMjU4NGJhMTA2MGUzYTI4ODk2
11
- ODhhYmQ1MWQ0ZjM0MDA3ZDU4OWEyNDJjMDExYjY4ODk2MWE1MDk=
12
- data.tar.gz: !binary |-
13
- NWI4YmYxMDMxNWZkMWQxYTZjZTIyODQ1MjdiYjkxMWIwZjYzM2E1MDM3MDk1
14
- M2Y5ZTU5YWQ4ODcwNTk4ZDQ0NWE0ZjA1NzMzOTI1MTQyMGQ0NzQ5MDE3MzFi
15
- YjJmYzVlNTQxNmQ5ZjUyMWQyNzZkZjU5NDMxNjQxZTIzMjA5YTc=
6
+ metadata.gz: a90ccfd4d4aa1893c315e161545a3bd04cdddcdaabdc98f7e4daf809a7a8acbefd3e15d03344fd933ae83e290b7ff3f4bdd2c15b0180565d4b00597c4c7d9e74
7
+ data.tar.gz: 1686b9cfa601e45f89590446c8c69a65f9c6f80b775f4031056fc6f9438c790514f836d7f00622ce31b0562d92e62c643aa19da5a53491c92d08cb2289be1ec8
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Attune
2
2
 
3
- A client for the [Attune ranking API](http://attune.co/). Build using the excellent [faraday](https://github.com/lostisland/faraday) library.
3
+ A client for the [Attune ranking API](http://attune.co/). Built using the excellent [faraday](https://github.com/lostisland/faraday) library.
4
+
5
+ * [Github](https://github.com/DigitalStripe/attune-ruby)
6
+ * [RubyGems](https://rubygems.org/gems/attune)
7
+ * [Documentation](http://rdoc.info/github/DigitalStripe/attune-ruby)
4
8
 
5
9
  ## Installation
6
10
 
@@ -55,22 +59,24 @@ The client can then perform rankings
55
59
  ``` ruby
56
60
  class ProductsController
57
61
  def index
58
- @products = Product.all
62
+ @products = sorted(Product.all)
63
+ end
59
64
 
65
+ private
66
+ def sorted products
60
67
  ranking = attune_client.get_ranking(
61
68
  id: session[:attune_id],
62
69
  view: request.fullpath,
63
70
  collection: 'products',
64
- entities: @products.map(&:id)
71
+ entities: products.map(&:id)
65
72
  )
66
- @products.sort_by do |product|
73
+ products.sort_by do |product|
67
74
  ranking.index(product.id.to_s)
68
75
  end
69
76
  end
70
77
  end
71
78
  ```
72
79
 
73
-
74
80
  ### Configuration
75
81
 
76
82
  Attune can be configured globally
@@ -88,9 +94,26 @@ Settings can also be overridden on a client object
88
94
  client = Attune::Client.new(timeout: 2)
89
95
  ```
90
96
 
97
+ See the documentation for
98
+ [Attune::Configurable](http://rdoc.info/github/DigitalStripe/attune-ruby/master/Attune/Configurable)
99
+ and the
100
+ [default configuration](http://rdoc.info/github/DigitalStripe/attune-ruby/master/Attune/Default)
101
+ for more details.
102
+
103
+ ### Testing
104
+
105
+ For testing and development, the ranking API can be simulated using.
106
+
107
+ ``` ruby
108
+ Attune.test_mode!
109
+ ```
110
+
111
+ In this mode no API calls will be made, and rankings will be returned in their original order.
112
+ Calling `.test_mode!` is equivalent to setting `disabled` to true and `exception_handler` to `:mock`.
113
+
91
114
  ## Contributing
92
115
 
93
- 1. Fork it ( http://github.com/freerunningtech/attune/fork )
116
+ 1. Fork it ( http://github.com/DigitalStripe/attune/fork )
94
117
  2. Create your feature branch (`git checkout -b my-new-feature`)
95
118
  3. Commit your changes (`git commit -am 'Add some feature'`)
96
119
  4. Push to the branch (`git push origin my-new-feature`)
data/attune.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["john@freerunningtechnologies.com"]
11
11
  spec.summary = %q{Client for the Attune product ranking API.}
12
12
  spec.description = %q{Client for the Attune product ranking API.}
13
- spec.homepage = "https://github.com/freerunningtech/attune-ruby"
13
+ spec.homepage = "https://github.com/DigitalStripe/attune-ruby"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rspec"
26
26
  spec.add_development_dependency "yard"
27
27
  spec.add_development_dependency "redcarpet"
28
+ spec.add_development_dependency "simplecov"
28
29
  end
data/lib/attune.rb CHANGED
@@ -9,4 +9,17 @@ module Attune
9
9
  def self.client
10
10
  Client.new
11
11
  end
12
+
13
+ # Simulate all API calls
14
+ # This is equivalent to setting disabled to true and exception_handler to
15
+ # :mock
16
+ def self.test_mode!
17
+ configure do |c|
18
+ c.exception_handler = :mock
19
+ c.disabled = true
20
+ end
21
+ end
22
+ def self.configure(&block)
23
+ Default.configure(&block)
24
+ end
12
25
  end
@@ -0,0 +1,52 @@
1
+ module Attune
2
+ class CallDropping < Faraday::Middleware
3
+ def initialize app, storage=default_storage
4
+ @app = app
5
+ @storage = storage
6
+ end
7
+
8
+ def call env
9
+ raise_timeout if should_skip?
10
+ begin
11
+ result = @app.call(env)
12
+ increment_skips(-SKIP_STEP)
13
+ result
14
+ rescue Faraday::Error::TimeoutError => e
15
+ increment_skips(SKIP_STEP)
16
+ raise e
17
+ end
18
+ end
19
+
20
+ private
21
+ # requests to skip before retry
22
+ SKIP_STEP = 0.25
23
+
24
+ # The most requests to skip before retrying
25
+ SKIP_MAX = 10.0
26
+
27
+ def raise_timeout
28
+ raise Faraday::Error::TimeoutError, "dropped request"
29
+ end
30
+
31
+ def should_skip?
32
+ rand > (1.0 / (1.0 + skip_rate))
33
+ end
34
+
35
+ def increment_skips amount
36
+ self.skip_rate = skip_rate + amount
37
+
38
+ if skip_rate <= 0.0
39
+ self.skip_rate = 0.0
40
+ elsif skip_rate >= SKIP_MAX
41
+ self.skip_rate = SKIP_MAX
42
+ end
43
+ end
44
+
45
+ def skip_rate; @storage[:skip_rate] || 0.0; end
46
+ def skip_rate= v; @storage[:skip_rate]= v; end
47
+
48
+ def default_storage
49
+ Thread.current
50
+ end
51
+ end
52
+ end
data/lib/attune/client.rb CHANGED
@@ -1,8 +1,12 @@
1
1
  require 'json'
2
2
 
3
3
  module Attune
4
+ class DisabledException < Faraday::Error::ClientError
5
+ def initialize(message="Attune library disabled though config")
6
+ super(message)
7
+ end
8
+ end
4
9
 
5
- # Client for the attune
6
10
  class Client
7
11
  include Attune::Configurable
8
12
 
@@ -38,14 +42,19 @@ module Attune
38
42
  # @option options [String] :user_agent The user agent for the application used by the anonymous users
39
43
  # @return id [String]
40
44
  # @raise [ArgumentError] if user_agent is not provided
45
+ # @raise [Faraday::Error] if the request fails or exceeds the timeout
41
46
  def create_anonymous(options)
42
47
  raise ArgumentError, "user_agent required" unless options[:user_agent]
43
48
  if id = options[:id]
44
- response = put("anonymous/#{id}", {user_agent: options[:user_agent]})
49
+ put("anonymous/#{id}", {user_agent: options[:user_agent]})
45
50
  id
46
51
  else
47
- response = post("anonymous", {user_agent: options[:user_agent]})
48
- response[:location][/\Aurn:id:([a-z0-9\-]+)\Z/, 1]
52
+ if response = post("anonymous", {user_agent: options[:user_agent]})
53
+ response[:location][/\Aurn:id:([a-z0-9\-]+)\Z/, 1]
54
+ else
55
+ # Return a new UUID if there was an exception and we're in mock mode
56
+ SecureRandom.uuid
57
+ end
49
58
  end
50
59
  end
51
60
 
@@ -67,10 +76,15 @@ module Attune
67
76
  # @option options [String] :customer id of customer (optional)
68
77
  # @return ranking [Array<String>] The entities in their ranked order
69
78
  # @raise [ArgumentError] if required parameters are missing
79
+ # @raise [Faraday::Error] if the request fails or exceeds the timeout
70
80
  def get_rankings(options)
71
81
  qs = encoded_ranking_params(options)
72
- response = get("rankings/#{qs}", customer: options.fetch(:customer, 'none'))
73
- JSON.parse(response.body)['ranking']
82
+ if response = get("rankings/#{qs}", customer: options.fetch(:customer, 'none'))
83
+ JSON.parse(response.body)['ranking']
84
+ else
85
+ # In mock mode: return the entities in the order passed in
86
+ options[:entities]
87
+ end
74
88
  end
75
89
 
76
90
  # Get multiple rankings in one call
@@ -92,14 +106,21 @@ module Attune
92
106
  # ])
93
107
  # @param [Array<Hash>] multi_options An array of options (see #get_rankings)
94
108
  # @return [Array<Array<String>>] rankings
109
+ # @raise [Faraday::Error] if the request fails or exceeds the timeout
95
110
  def multi_get_rankings(multi_options)
96
111
  requests = multi_options.map do |options|
97
112
  encoded_ranking_params(options)
98
113
  end
99
- response = get("rankings", ids: requests)
100
- results = JSON.parse(response.body)['results']
101
- results.values.map do |result|
102
- result['ranking']
114
+ if response = get("rankings", ids: requests)
115
+ results = JSON.parse(response.body)['results']
116
+ results.values.map do |result|
117
+ result['ranking']
118
+ end
119
+ else
120
+ # In mock mode: return the entities in the order passed in
121
+ multi_options.map do |options|
122
+ options[:entities]
123
+ end
103
124
  end
104
125
  end
105
126
 
@@ -112,6 +133,7 @@ module Attune
112
133
  # '25892e17-80f6-415f-9c65-7395632f022',
113
134
  # 'cd171f7c-560d-4a62-8d65-16b87419a58'
114
135
  # )
136
+ # @raise [Faraday::Error] if the request fails or exceeds the timeout
115
137
  def bind(id, customer_id)
116
138
  put("bindings/anonymous=#{id}&customer=#{customer_id}")
117
139
  true
@@ -131,27 +153,32 @@ module Attune
131
153
 
132
154
  def get(path, params={})
133
155
  adapter.get(path, params)
134
- rescue Faraday::ClientError => e
156
+ rescue Faraday::Error::ClientError => e
135
157
  handle_exception(e)
136
158
  end
137
159
 
138
160
  def put(path, params={})
139
161
  adapter.put(path, ::JSON.dump(params))
140
- rescue Faraday::ClientError => e
162
+ rescue Faraday::Error::ClientError => e
141
163
  handle_exception(e)
142
164
  end
143
165
 
144
166
  def post(path, params={})
145
167
  adapter.post(path, ::JSON.dump(params))
146
- rescue Faraday::ClientError => e
168
+ rescue Faraday::Error::ClientError => e
147
169
  handle_exception(e)
148
170
  end
149
171
 
150
172
  def handle_exception e
151
- raise e
173
+ if exception_handler == :mock
174
+ nil
175
+ else
176
+ raise e
177
+ end
152
178
  end
153
179
 
154
180
  def adapter
181
+ raise DisabledException if disabled?
155
182
  Faraday.new(url: endpoint, builder: middleware, request: {timeout: timeout})
156
183
  end
157
184
  end
@@ -4,6 +4,7 @@ module Attune
4
4
  :endpoint,
5
5
  :middleware,
6
6
  :disabled,
7
+ :exception_handler,
7
8
  :timeout
8
9
  ]
9
10
 
@@ -15,10 +16,23 @@ module Attune
15
16
 
16
17
  # FIXME
17
18
  attr_accessor :disabled
19
+ alias_method :disabled?, :disabled
18
20
 
19
21
  # Time (in seconds) to wait for requests to finish
20
22
  attr_accessor :timeout
21
23
 
24
+ # How to deal with HTTP exceptions
25
+ # @param [:mock, :raise] handler Method used for handling exceptions.
26
+ # @raise [ArgumentError] if handler is not :mock or :raise
27
+ attr_reader :exception_handler
28
+ def exception_handler= handler
29
+ if [:mock, :raise].include?(handler)
30
+ @exception_handler = handler
31
+ else
32
+ raise ArgumentError, "exception_handler must be :mock or :raise"
33
+ end
34
+ end
35
+
22
36
  # @example configure
23
37
  # Attune.configure do |c|
24
38
  # c.endpoint = "http://example.com:8080/"
@@ -1,4 +1,5 @@
1
1
  require 'attune/param_flattener'
2
+ require "attune/call_dropping"
2
3
  require "attune/json_logger"
3
4
 
4
5
  module Attune
@@ -12,6 +13,9 @@ module Attune
12
13
  # Needed for encoding of BATCH GET requests
13
14
  builder.use Attune::ParamFlattener
14
15
 
16
+ # Log all requests
17
+ builder.use Attune::CallDropping
18
+
15
19
  # Allow one retry per request
16
20
  builder.request :retry, 1
17
21
 
@@ -27,6 +31,7 @@ module Attune
27
31
  c.endpoint = ENDPOINT
28
32
  c.middleware = MIDDLEWARE
29
33
  c.disabled = false
34
+ c.exception_handler = :raise
30
35
  c.timeout = 1
31
36
  end
32
37
  end
@@ -1,3 +1,3 @@
1
1
  module Attune
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Attune::CallDropping do
4
+ let(:stubs){ Faraday::Adapter::Test::Stubs.new }
5
+ let(:connection) do
6
+ Faraday.new(url: 'http://example.com/') do |builder|
7
+ builder.use described_class, storage
8
+ builder.adapter :test, stubs
9
+ end
10
+ end
11
+ let(:response){ connection.get("/") }
12
+ let(:timeout){ Faraday::Error::TimeoutError.new("simulated timeout") }
13
+
14
+ context "using default storage" do
15
+ let(:connection) do
16
+ Faraday.new(url: 'http://example.com/') do |builder|
17
+ builder.use described_class
18
+ builder.adapter :test, stubs
19
+ end
20
+ end
21
+ it "can be initialized" do
22
+ stubs.get("/"){ [200, {}, "foobar"] }
23
+ expect(response.body).to eq "foobar"
24
+ stubs.verify_stubbed_calls
25
+ end
26
+ end
27
+
28
+ context "without previous timeouts" do
29
+ let(:storage){ {} }
30
+ context "no timeout" do
31
+ it "runs request" do
32
+ stubs.get("/"){ [200, {}, "foobar"] }
33
+ expect(response.body).to eq "foobar"
34
+ expect(storage).to eq(skip_rate: 0.0)
35
+ stubs.verify_stubbed_calls
36
+ end
37
+ end
38
+
39
+ context "with a timeout" do
40
+ it "raises the timeout" do
41
+ stubs.get("/"){ raise timeout }
42
+ expect {
43
+ response
44
+ }.to raise_exception(Faraday::Error::TimeoutError)
45
+ expect(storage).to eq(skip_rate: 0.25)
46
+ stubs.verify_stubbed_calls
47
+ end
48
+ end
49
+ end
50
+
51
+ context "with an existing skip rate" do
52
+ let(:storage){ {skip_rate: 1.0} }
53
+ before{ described_class.any_instance.stub(rand: random) }
54
+ context "request skipped" do
55
+ let(:random){ 1 }
56
+ it "raises timeout" do
57
+ expect {
58
+ response
59
+ }.to raise_exception(Faraday::Error::TimeoutError)
60
+ expect(storage).to eq(skip_rate: 1.00)
61
+ end
62
+ end
63
+
64
+ context "request attempted" do
65
+ context "at max drop rate" do
66
+ let(:storage){ {skip_rate: 10.0} }
67
+ it "leaves drop rate unchanged" do
68
+ stubs.get("/"){ raise timeout }
69
+ expect { response }.to raise_exception(Faraday::Error::TimeoutError)
70
+ expect(storage).to eq(skip_rate: 10.0)
71
+ stubs.verify_stubbed_calls
72
+ end
73
+ end
74
+
75
+ let(:random){ 0 }
76
+ it "succeeds an reduces skip rate" do
77
+ stubs.get("/"){ [200, {}, "foobar"] }
78
+ expect(response.body).to eq "foobar"
79
+ expect(storage).to eq(skip_rate: 0.75)
80
+ stubs.verify_stubbed_calls
81
+ end
82
+ end
83
+ end
84
+ end
@@ -24,6 +24,63 @@ describe Attune::Client do
24
24
  end
25
25
  end
26
26
 
27
+ describe "API errors" do
28
+ it "will raise timeout" do
29
+ stubs.post("anonymous", %[{"user_agent":"Mozilla/5.0"}]){ raise Faraday::Error::TimeoutError.new("test") }
30
+ expect {
31
+ client.create_anonymous(user_agent: 'Mozilla/5.0')
32
+ }.to raise_exception(Faraday::Error::TimeoutError)
33
+ stubs.verify_stubbed_calls
34
+ end
35
+ it "will raise ConnectionFailed" do
36
+ stubs.post("anonymous", %[{"user_agent":"Mozilla/5.0"}]){ raise Faraday::Error::ConnectionFailed.new("test") }
37
+ expect {
38
+ client.create_anonymous(user_agent: 'Mozilla/5.0')
39
+ }.to raise_exception(Faraday::Error::ConnectionFailed)
40
+ stubs.verify_stubbed_calls
41
+ end
42
+ end
43
+
44
+ describe "disabled" do
45
+ context "with raise" do
46
+ let(:options){ {disabled: true, exception_handler: :raise} }
47
+ it "will raise DisalbedException" do
48
+ expect {
49
+ client.create_anonymous(user_agent: 'Mozilla/5.0')
50
+ }.to raise_exception(Attune::DisabledException)
51
+ end
52
+ end
53
+ context "with mock" do
54
+ let(:options){ {disabled: true, exception_handler: :mock} }
55
+ it "mocks create_anonymous with an id" do
56
+ result = client.create_anonymous(id: '12345', user_agent: 'Mozilla/5.0')
57
+ expect(result).to eq('12345')
58
+ end
59
+ it "mocks create_anonymous with no id" do
60
+ result = client.create_anonymous(user_agent: 'Mozilla/5.0')
61
+ expect(result).to match(/^[a-z0-9\-]+$/)
62
+ end
63
+ it "mocks get_rankings" do
64
+ result = client.get_rankings(
65
+ id: 'abcd123',
66
+ view: 'b/mens-pants',
67
+ collection: 'products',
68
+ entities: %w[1001, 1002, 1003, 1004]
69
+ )
70
+ expect(result).to eq %w[1001, 1002, 1003, 1004]
71
+ end
72
+ it "mocks multi_get_rankings" do
73
+ result = client.multi_get_rankings([
74
+ id: 'abcd123',
75
+ view: 'b/mens-pants',
76
+ collection: 'products',
77
+ entities: %w[1001, 1002, 1003, 1004]
78
+ ])
79
+ expect(result).to eq [%w[1001, 1002, 1003, 1004]]
80
+ end
81
+ end
82
+ end
83
+
27
84
  it "can create_anonymous generating an id" do
28
85
  stubs.post("anonymous", %[{"user_agent":"Mozilla/5.0"}]){ [200, {location: 'urn:id:abcd123'}, nil] }
29
86
  id = client.create_anonymous(user_agent: 'Mozilla/5.0')
data/spec/attune_spec.rb CHANGED
@@ -9,4 +9,18 @@ describe Attune do
9
9
  specify { expect(subject.endpoint).to eq 'http://localhost/' }
10
10
  specify { expect(subject.disabled).to eq false }
11
11
  end
12
+ describe 'configure' do
13
+ it "yields with Attune::Default" do
14
+ Attune.configure do |c|
15
+ expect(c).to be Attune::Default
16
+ end
17
+ end
18
+ end
19
+ describe 'test_mode' do
20
+ it "sets correct test options" do
21
+ expect(Attune::Default).to receive(:exception_handler=).with(:mock)
22
+ expect(Attune::Default).to receive(:disabled=).with(true)
23
+ Attune.test_mode!
24
+ end
25
+ end
12
26
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,9 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/vendor'
4
+ add_filter '/spec'
5
+ end
6
+
1
7
  require 'attune'
2
8
 
3
9
  # This file was generated by the `rspec --init` command. Conventionally, all
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attune
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-17 00:00:00.000000000 Z
11
+ date: 2013-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
@@ -42,56 +42,70 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ! '>='
73
+ - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: redcarpet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  description: Client for the Attune product ranking API.
@@ -111,18 +125,20 @@ files:
111
125
  - Rakefile
112
126
  - attune.gemspec
113
127
  - lib/attune.rb
128
+ - lib/attune/call_dropping.rb
114
129
  - lib/attune/client.rb
115
130
  - lib/attune/configurable.rb
116
131
  - lib/attune/default.rb
117
132
  - lib/attune/json_logger.rb
118
133
  - lib/attune/param_flattener.rb
119
134
  - lib/attune/version.rb
135
+ - spec/attune/call_dropping_spec.rb
120
136
  - spec/attune/client_spec.rb
121
137
  - spec/attune/json_logger_spec.rb
122
138
  - spec/attune_spec.rb
123
139
  - spec/remote_spec.rb
124
140
  - spec/spec_helper.rb
125
- homepage: https://github.com/freerunningtech/attune-ruby
141
+ homepage: https://github.com/DigitalStripe/attune-ruby
126
142
  licenses:
127
143
  - MIT
128
144
  metadata: {}
@@ -132,21 +148,22 @@ require_paths:
132
148
  - lib
133
149
  required_ruby_version: !ruby/object:Gem::Requirement
134
150
  requirements:
135
- - - ! '>='
151
+ - - '>='
136
152
  - !ruby/object:Gem::Version
137
153
  version: '0'
138
154
  required_rubygems_version: !ruby/object:Gem::Requirement
139
155
  requirements:
140
- - - ! '>='
156
+ - - '>='
141
157
  - !ruby/object:Gem::Version
142
158
  version: '0'
143
159
  requirements: []
144
160
  rubyforge_project:
145
- rubygems_version: 2.1.9
161
+ rubygems_version: 2.1.11
146
162
  signing_key:
147
163
  specification_version: 4
148
164
  summary: Client for the Attune product ranking API.
149
165
  test_files:
166
+ - spec/attune/call_dropping_spec.rb
150
167
  - spec/attune/client_spec.rb
151
168
  - spec/attune/json_logger_spec.rb
152
169
  - spec/attune_spec.rb