jahuty 2.1.0 → 3.2.1

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,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a3b0216b333e26ac504fbc1a5329d13a8dbab1ec0de605fcb8ae8f8976bb728c
4
- data.tar.gz: 6b9a6932abd413f52c4cba2b7e4bd4047b443ce625e25d2083a9f8c5d76c4f15
3
+ metadata.gz: fd60e0f72d6931901570d8d0112c23013233b95553dc1e0bfccdf54dc1dfb74c
4
+ data.tar.gz: 124d15d9a8f8dfd8939326ed2c49067fb59c90b2e1b254cac7d53f432090f66c
5
5
  SHA512:
6
- metadata.gz: 4133af6f9a17eea018ce7ca98466ef631214160329d9aaaa42fe3272792391fc4c7deb166cafaa7c37491fc24502e7a5f494eaa93dc5f882fc65a95b216a089c
7
- data.tar.gz: 6e7e074e20eda91bd5d000af585a4a46d3f9886a07dd3d24a9c4b811f78398787e116bca05e356eb591088ffd4ad4eef779fdff066c48fb4afd17b504b6d04db
6
+ metadata.gz: c80df676479909e5ba76bfe714943fa8b8803a51fac8cdae911d8ff0e5899aff3af5db1bf04ec6ee4001dd4eb8e27a6a988b7be2d4615bac020dc704cc0e7239
7
+ data.tar.gz: 6ff131d938e8b209bdc524f3dbb87de1a735951e476bb95ba8e5dcce558a2bc7c8be66fc22eb39390f00490631f1dfac251fe3664f5344b3bdb5f918ad874291
@@ -0,0 +1,33 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+ codecov: codecov/codecov@1.1.3
5
+ jobs:
6
+ build:
7
+ docker:
8
+ - image: circleci/ruby:2.6.3-stretch-node
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Update bundler
14
+ command: gem install bundler
15
+ - run:
16
+ name: Which bundler?
17
+ command: bundle -v
18
+ - ruby/bundle-install
19
+ - run:
20
+ name: Run rubocop
21
+ command: bundle exec rake rubocop
22
+ - run:
23
+ name: Run specs
24
+ command: |
25
+ bundle exec rspec --profile 10 \
26
+ --format RspecJunitFormatter \
27
+ --out test_results/rspec.xml \
28
+ --format progress \
29
+ $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
30
+ - store_test_results:
31
+ path: test_results
32
+ - codecov/upload:
33
+ file: ./coverage/coverage.xml
data/.rubocop.yml ADDED
@@ -0,0 +1,23 @@
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rspec
4
+ AllCops:
5
+ TargetRubyVersion: 2.6
6
+ NewCops: enable
7
+ Exclude:
8
+ - vendor/bundle/**/*
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - 'jahuty.gemspec'
12
+ - 'Rakefile'
13
+ - '**/*.rake'
14
+ - 'spec/**/*.rb'
15
+ Metrics/ModuleLength:
16
+ Exclude:
17
+ - 'spec/**/*.rb'
18
+ RSpec/ExampleLength:
19
+ Exclude:
20
+ - 'spec/jahuty/system_spec.rb'
21
+ RSpec/MultipleExpectations:
22
+ Exclude:
23
+ - 'spec/jahuty/system_spec.rb'
data/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 3.2.1 - 2020-03-16
9
+
10
+ * Fix issue with double-enveloping the `params` query string parameter.
11
+ * Add system tests for params, caching, problems, and collections.
12
+
13
+ ## 3.2.0 - 2020-03-08
14
+
15
+ * Added collections to the library with `all_renders` method. This was a rather large change and required adding new objects like `Action::Show`, refactoring old ones like `Resource::Factory`, and removing some objects like `Cache::Manager` and `Service::Factory` which added unnecessary complexity.
16
+ * Added `snippet_id` to `Resource::Render` to help keep track of a render's parent snippet.
17
+
18
+ ## 3.1.1 - 2020-02-26
19
+
20
+ - Add support for extra, unused attributes returned by the API to support evolution.
21
+ - Fix the `method redefined` warnings in `cache/manager_spec.rb` and `cache/facade_spec.rb`.
22
+ - Fix the `expect { }.not_to raise_error(SpecificErrorClass)` false positives warnings in `resource/render_spec.rb`.
23
+
24
+ ## 3.1.0 - 2020-01-04
25
+
26
+ - Add caching support for any cache implementation that supports `get/set` or `read/write` methods.
27
+ - Default to using in-memory [mini-cache](https://github.com/derrickreimer/mini_cache) storage.
28
+
29
+ ## 3.0.0 - 2020-12-30
30
+
31
+ - Change from a static-based architecture (e.g., `Jahuty::Snippet.render(1)`) to an instance-based one (e.g., `jahuty.snippets.render(1)`) to make the library easier to develop, test, and use.
32
+ - Change `README` and fix broken links from `www.jahuty.com/docs` to `docs.jahuty.com`.
33
+ - Add [CircleCI](https://circleci.com/gh/jahuty/jahuty-ruby) continuous integration.
34
+ - Add [Rubocop](https://github.com/rubocop-hq/rubocop) code analyzer and formatter, based on the community style guide.
35
+ - Add code coverage analysis with [Simplecov](https://github.com/simplecov-ruby/simplecov) and [Codecov.io](https://codecov.io/gh/jahuty/jahuty-ruby).
36
+
8
37
  ## 2.0.0 - 2020-07-04
9
38
 
10
39
  - Change `Service::Get` to `Service::Render`.
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in jahuty.gemspec
4
6
  gemspec
data/README.md CHANGED
@@ -1,96 +1,233 @@
1
+ [![CircleCI](https://circleci.com/gh/jahuty/jahuty-ruby.svg?style=svg)](https://circleci.com/gh/jahuty/jahuty-ruby) [![codecov](https://codecov.io/gh/jahuty/jahuty-ruby/branch/master/graph/badge.svg?token=NLDCGGYB8S)](https://codecov.io/gh/jahuty/jahuty-ruby) [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop)
2
+
1
3
  # jahuty-ruby
2
- Welcome to [Jahuty's](https://www.jahuty.com) Ruby SDK!
4
+
5
+ Welcome to the [Ruby SDK](https://docs.jahuty.com/sdks/ruby) for [Jahuty's API](https://docs.jahuty.com/api)!
3
6
 
4
7
  ## Installation
5
8
 
6
- This library requires [Ruby 2.3+](https://www.ruby-lang.org/en/downloads/releases/).
9
+ This library requires [Ruby 2.6+](https://www.ruby-lang.org/en/downloads/releases/).
7
10
 
8
11
  It is multi-platform, and we strive to make it run equally well on Windows, Linux, and OSX.
9
12
 
10
- Add this line to your application's `Gemfile`:
13
+ To install, add this line to your application's `Gemfile` and run `bundle install`:
11
14
 
12
15
  ```ruby
13
- gem "jahuty", "~> 2.0"
14
- ```
15
-
16
- And then execute:
17
-
18
- ```bash
19
- $ bundle
16
+ gem 'jahuty', '~> 3.2'
20
17
  ```
21
18
 
22
19
  ## Usage
23
20
 
24
- Before use, the library needs to be configured with your [API key](https://www.jahuty.com/docs/api#authentication) (ideally, once during startup):
21
+ Instantiate the client with your [API key](https://docs.jahuty.com/api#authentication) and use `snippets.render` to render your snippet:
25
22
 
26
23
  ```ruby
27
- require "jahuty"
24
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
28
25
 
29
- Jahuty.key = "YOUR_API_KEY"
26
+ puts jahuty.snippets.render YOUR_SNIPPET_ID
30
27
  ```
31
28
 
32
- With the API key set, you can use the `Snippet.render` method to render a snippet:
29
+ You can access the render's content with `to_s` or `content`:
33
30
 
34
31
  ```ruby
35
- require "jahuty"
32
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
36
33
 
37
- # retrieve the snippet
38
- render = Snippet.render YOUR_SNIPPET_ID
34
+ render = jahuty.snippets.render YOUR_SNIPPET_ID
39
35
 
40
- # convert it to a string
41
- render.to_s
36
+ a = render.to_s
42
37
 
43
- # or, access its attributes
44
- render.content
38
+ b = render.content
39
+
40
+ a == b # returns true
45
41
  ```
46
42
 
47
43
  In an HTML view:
48
44
 
49
45
  ```html+erb
50
- <%-
51
- require "jahuty"
52
-
53
- Jahuty.key = "YOUR_API_KEY"
54
- %>
46
+ <%- jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY') -%>
55
47
  <!doctype html>
56
48
  <html>
57
49
  <head>
58
50
  <title>Awesome example</title>
59
51
  </head>
60
52
  <body>
61
- <%= Snippet.render YOUR_SNIPPET_ID %>
53
+ <%== jahuty.snippets.render YOUR_SNIPPET_ID %>
62
54
  </body>
63
55
  ```
64
56
 
57
+ You can also use tags to render a collection of snippets with the `snippets.all_renders` method:
58
+
59
+ ```ruby
60
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
61
+
62
+ renders = jahuty.snippets.all_renders 'YOUR_TAG'
63
+
64
+ renders.each { |render| puts render }
65
+ ```
66
+
65
67
  ## Parameters
66
68
 
67
- You can [pass parameters](https://www.jahuty.com/docs/passing-a-parameter) into your snippet using the `params` key of the options hash:
69
+ You can [pass parameters](https://docs.jahuty.com/liquid/parameters) into your renders using the `params` option:
68
70
 
69
71
  ```ruby
70
- require "jahuty"
72
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
71
73
 
72
- Snippet.render(YOUR_SNIPPET_ID, params: { foo: "bar" });
74
+ jahuty.snippets.render YOUR_SNIPPET_ID, params: { foo: 'bar' }
73
75
  ```
74
76
 
75
- The parameters above would be equivalent to [assigning the variables](https://www.jahuty.com/docs/assigning-a-variable) below in your snippet:
77
+ The parameters above would be equivalent to [assigning the variable](https://docs.jahuty.com/liquid/variables) below in your snippet:
76
78
 
77
79
  ```html
78
80
  {% assign foo = "bar" %}
79
81
  ```
80
82
 
81
- ## Errors
83
+ If you're rendering a collection, the first dimension of the `params` key determines the parameters' scope. Use an asterisk key (`*`) to pass the same parameters to all snippets, or use a snippet id as key to pass parameters to a specific snippet.
84
+
85
+ ```ruby
86
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
87
+
88
+ jahuty.snippets.all_renders 'YOUR_TAG', params: {
89
+ '*' => { foo: 'bar' },
90
+ '1' => { baz: 'qux' }
91
+ }
92
+ ```
82
93
 
83
- If you don't set your API key before calling `Snippet.render`, a `StandardError` will be raised. If an error occurs with [Jahuty's API](https://www.jahuty.com/docs/api), a `NotOk` exception will be raised:
94
+ This will pass the params `{ foo: 'bar' }` to all snippets, except for snippet `1`, which will be passed `{ foo: 'bar', baz: 'qux' }`.
95
+
96
+ The two parameter lists will be merged recursively, and parameters for a specific snippet will take precedence over parameters for all snippets. For example, the parameter `foo` will be assigned the value `"bar"` for all snippets, except for snippet `1`, where it will be assigned the value `"qux"`:
84
97
 
85
98
  ```ruby
86
- require "jahuty"
99
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
100
+
101
+ jahuty.snippets.all_renders 'YOUR_TAG', params: {
102
+ '*' => { foo: 'bar' },
103
+ '1' => { foo: 'qux' }
104
+ }
105
+ ```
106
+
107
+ ## Caching
108
+
109
+ You can use caching to control how frequently this library requests the latest content from Jahuty's API.
110
+
111
+ * When content is in _development_ (i.e., frequently changing and low traffic), you can use the default in-memory store to view content changes instantaneously with slower response times.
112
+ * When content is in _production_ (i.e., more stable and high traffic), you can use persistent caching to update content less frequently and improve your application's response time.
113
+
114
+ ### Caching in memory (default)
115
+
116
+ By default, this library uses an in-memory cache to avoid requesting the same render more than once during the same request lifecycle. For example:
117
+
118
+ ```ruby
119
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
120
+
121
+ # This call will send a synchronous API request; cache the result in memory;
122
+ # and, return the result to the caller.
123
+ render1 = jahuty.snippets.render YOUR_SNIPPET_ID
124
+
125
+ # This call skips sending an API request and uses the cached value instead.
126
+ render2 = jahuty.snippets.render YOUR_SNIPPET_ID
127
+ ```
128
+
129
+ The in-memory cache only persists for the duration of the original request, however. At the end of the request's lifecycle, the cache will be discarded. To store renders across requests, you need a persistent cache.
130
+
131
+ ### Caching persistently
132
+
133
+ A persistent cache allows renders to be cached across multiple requests. This reduces the number of synchronous network requests to Jahuty's API and improves your application's average response time.
134
+
135
+ To configure Jahuty to use your persistent cache, pass a cache implementation to the client via the `cache` configuration option:
136
+
137
+ ```ruby
138
+ jahuty = new Jahuty::Client.new(
139
+ api_key: 'YOUR_API_KEY',
140
+ cache: cache
141
+ )
142
+ ```
143
+
144
+ The persistent cache implementation you choose and configure is up to you. There are many libraries available, and most frameworks provide their own. At this time, we support any object which responds to `get(key)`/`set(key, value, expires_in:)` or `read(key)`/`write(key, value, expires_in:)` including [ActiveSupport::Cache::Store](https://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html#method-i-fetch).
87
145
 
146
+ ### Expiring
147
+
148
+ There are three methods for configuring this library's `:expires_in`, the amount of time between when a render is stored and when it's considered stale. From lowest-to-highest precedence, the methods are:
149
+
150
+ 1. configuring your caching implementation,
151
+ 1. configuring this library's default `:expires_in`, and
152
+ 1. configuring a render's `:expires_in`.
153
+
154
+ #### Configuring your caching implementation
155
+
156
+ You can usually configure your caching implementation with a default `:expires_in`. If no other `:expires_in` is configured, this library will defer to the caching implementation's default `:expires_in`.
157
+
158
+ #### Configuring this library's default `:expires_in`
159
+
160
+ You can configure a default `:expires_in` for all of this library's renders by passing an integer number of seconds via the client's `:expires_in` configuration option:
161
+
162
+ ```ruby
163
+ jahuty = Jahuty::Client.new(
164
+ api_key: 'YOUR_API_KEY',
165
+ cache: cache,
166
+ expires_in: 60 # <- Cache all renders for sixty seconds
167
+ )
168
+ ```
169
+
170
+ If this library's default `:expires_in` is set, it will take precedence over the default `:expires_in` of the caching implementation.
171
+
172
+ #### Configuring a render's `:expires_in`
173
+
174
+ You can configure `:expires_in` for individual renders by passing an integer number of seconds via the render method's `:expires_in` configuration option:
175
+
176
+ ```ruby
177
+ # Cache all renders 300 seconds (five minutes).
178
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY', cache: cache, expires_in: 300)
179
+
180
+ # Except, cache this render for 60 seconds.
181
+ render = jahuty.snippets.render YOUR_SNIPPET_ID, expires_in: 60
182
+
183
+ # Except, cache the renders in this collection for 120 seconds.
184
+ render = jahuty.snippets.all_renders 'YOUR_TAG', expires_in: 120
185
+ ```
186
+
187
+ If a render's `:expires_in` is set, it will take precedence over the library's default `:expires_in` and the caching implementation's `:expires_in`.
188
+
189
+ ### Caching collections
190
+
191
+ By default, this library will cache each render returned by `all_renders`:
192
+
193
+ ```ruby
194
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY', cache: cache)
195
+
196
+ # Sends a network request, caches each render, and returns the collection.
197
+ jahuty.snippets.all_renders 'YOUR_TAG';
198
+
199
+ # If this reder exists in the collection, the cached value will be used instead
200
+ # of sending a network request for the latest version.
201
+ jahuty.snippets.render YOUR_SNIPPET_ID;
202
+ ```
203
+
204
+ This is a powerful feature, especially when combined with a persistent cache. Using the `all_renders` method, you can render and cache an arbitrarily large chunk of content with a single network request. Because any subsequent call to `render` a snippet in the collection will use its cached version, you can reduce the number of network requests to load your content.
205
+
206
+ This method is even more powerful when combined with an asynchronous background job. When `all_renders` can be called outside your request cycle periodically, you can turn your cache into your content storage mechanism. You can render and cache dynamic content as frequently as you like without any hit to your application's response time.
207
+
208
+ ### Disabling caching
209
+
210
+ You can disable caching, even the default in-memory caching, by passing an `:expires_in` of zero (`0`) or a negative integer (e.g., `-1`) via any of the methods described above. For example:
211
+
212
+ ```ruby
213
+ # Disable all caching.
214
+ jahuty1 = Jahuty::Client.new(api_key: 'YOUR_API_KEY', expires_in: 0)
215
+
216
+ # Disable caching for this render.
217
+ jahuty2 = Jahuty::Client.new(api_key: 'YOUR_API_KEY', expires_in: 60)
218
+ jahuty2.snippets.render 1, expires_in: 0
219
+ ```
220
+
221
+ ## Errors
222
+
223
+ If an error occurs with [Jahuty's API](https://docs.jahuty.com/api#errors), a `Jahuty::Exception::Error` will be raised:
224
+
225
+ ```ruby
88
226
  begin
89
- Snippet.render YOUR_SNIPPET_ID
90
- rescue StandardError => e
91
- # hmm, did you set the API key first?
92
- rescue Jahuty::Exception::NotOk => e
93
- # hmm, the API returned something besides 2xx status code
227
+ jahuty = Jahuty::Client.new(api_key: 'YOUR_API_KEY')
228
+ jahuty.snippets.render YOUR_SNIPPET_ID
229
+ rescue Jahuty::Exception::Error => e
230
+ # The API returned an error. See the error's problem for details.
94
231
  puts e.problem.type # a URL to more information
95
232
  puts e.problem.status # the status code
96
233
  puts e.problem.detail # a description of the error
data/Rakefile CHANGED
@@ -1,6 +1,14 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
3
6
 
4
7
  RSpec::Core::RakeTask.new(:spec)
5
8
 
6
- task :default => :spec
9
+ task default: :spec
10
+
11
+ RuboCop::RakeTask.new do |task|
12
+ task.requires << 'rubocop-performance'
13
+ task.requires << 'rubocop-rspec'
14
+ end
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "jahuty/snippets"
4
+ require 'bundler/setup'
5
+ require 'jahuty/snippets'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "jahuty/snippets"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/bin/setup CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bash
2
+ # frozen_string_literal: true
3
+
2
4
  set -euo pipefail
3
5
  IFS=$'\n\t'
4
6
  set -vx
data/jahuty.gemspec CHANGED
@@ -1,30 +1,47 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
- require "jahuty"
6
+ require 'jahuty/version'
6
7
 
7
8
  Gem::Specification.new do |spec|
8
- spec.name = "jahuty"
9
+ spec.name = 'jahuty'
9
10
  spec.version = Jahuty::VERSION
10
- spec.authors = ["Jack Clayton"]
11
- spec.email = ["jack@jahuty.com"]
11
+ spec.authors = ['Jack Clayton']
12
+ spec.email = ['jack@jahuty.com']
12
13
 
13
- spec.summary = %q{Jahuty's Ruby SDK.}
14
- spec.description = %q{Turn any page into a content-managed page.}
15
- spec.homepage = "https://github.com/jahuty/jahuty-ruby"
16
- spec.license = "MIT"
14
+ spec.summary = 'Jahuty\'s Ruby SDK.'
15
+ spec.description = 'Turn any page into a content-managed page.'
16
+ spec.homepage = 'https://www.jahuty.com'
17
+ spec.license = 'MIT'
17
18
 
18
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = 'https://github.com/jahuty/jahuty-ruby'
23
+ spec.metadata['changelog_uri'] = 'https://github.com/jahuty/jahuty-ruby/blob/master/CHANGELOG.md'
24
+
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
27
  end
21
- spec.bindir = "exe"
28
+ spec.bindir = 'exe'
22
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
- spec.require_paths = ["lib"]
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.required_ruby_version = '~> 2.6'
24
33
 
25
- spec.add_dependency "faraday", "~> 1.0"
34
+ spec.add_dependency 'faraday', '~> 1.0'
35
+ spec.add_dependency 'mini_cache', '~> 1.1'
26
36
 
27
- spec.add_development_dependency "bundler", "~> 2.0"
28
- spec.add_development_dependency "rake", "~> 12.3"
29
- spec.add_development_dependency "rspec", "~> 3.0"
37
+ spec.add_development_dependency 'bundler', '~> 2.0'
38
+ spec.add_development_dependency 'rake', '~> 12.3'
39
+ spec.add_development_dependency 'rspec', '~> 3.0'
40
+ spec.add_development_dependency 'rspec_junit_formatter', '~>0.4'
41
+ spec.add_development_dependency 'rubocop', '~> 1.7'
42
+ spec.add_development_dependency 'rubocop-performance', '~> 1.9'
43
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.1'
44
+ spec.add_development_dependency 'simplecov', '~>0.20'
45
+ spec.add_development_dependency 'simplecov-cobertura', '~> 1.4'
46
+ spec.add_development_dependency 'webmock', '~> 3.11'
30
47
  end