mailchimp_api_v3 0.0.0 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -6
  3. data/circle.yml +5 -0
  4. data/lib/{mailchimp → mailchimp_api_v3}/account.rb +2 -3
  5. data/lib/{mailchimp → mailchimp_api_v3}/client/remote.rb +5 -6
  6. data/lib/{mailchimp → mailchimp_api_v3}/client.rb +15 -10
  7. data/lib/{mailchimp → mailchimp_api_v3}/collection/paging.rb +1 -1
  8. data/lib/{mailchimp → mailchimp_api_v3}/collection.rb +16 -9
  9. data/lib/{mailchimp → mailchimp_api_v3}/exception.rb +13 -9
  10. data/lib/mailchimp_api_v3/instance.rb +62 -0
  11. data/lib/mailchimp_api_v3/interest.rb +10 -0
  12. data/lib/{mailchimp → mailchimp_api_v3}/interest_categories.rb +4 -4
  13. data/lib/mailchimp_api_v3/interest_category.rb +16 -0
  14. data/lib/{mailchimp → mailchimp_api_v3}/interests.rb +4 -4
  15. data/lib/mailchimp_api_v3/list.rb +26 -0
  16. data/lib/{mailchimp → mailchimp_api_v3}/lists.rb +4 -4
  17. data/lib/mailchimp_api_v3/member.rb +55 -0
  18. data/lib/{mailchimp → mailchimp_api_v3}/members.rb +4 -4
  19. data/lib/mailchimp_api_v3/version.rb +3 -0
  20. data/mailchimp_api_v3.gemspec +5 -5
  21. data/spec/fixtures/cassettes/mailchimp.yml +335 -73
  22. data/spec/fixtures/cassettes/members.yml +16 -16
  23. data/spec/mailchimp/account_spec.rb +5 -5
  24. data/spec/mailchimp/client_spec.rb +10 -10
  25. data/spec/mailchimp/exception_spec.rb +22 -14
  26. data/spec/mailchimp/interest_categories_spec.rb +10 -10
  27. data/spec/mailchimp/interest_category_spec.rb +5 -5
  28. data/spec/mailchimp/interest_spec.rb +4 -4
  29. data/spec/mailchimp/interests_spec.rb +8 -8
  30. data/spec/mailchimp/list_spec.rb +25 -6
  31. data/spec/mailchimp/lists_spec.rb +4 -4
  32. data/spec/mailchimp/member_spec.rb +28 -4
  33. data/spec/mailchimp/members_spec.rb +5 -5
  34. data/spec/mailchimp_spec.rb +6 -10
  35. data/spec/support/api_key.rb +8 -4
  36. data/spec/support/vcr_setup.rb +1 -0
  37. metadata +32 -20
  38. data/lib/mailchimp/instance.rb +0 -31
  39. data/lib/mailchimp/interest.rb +0 -9
  40. data/lib/mailchimp/interest_category.rb +0 -19
  41. data/lib/mailchimp/list.rb +0 -20
  42. data/lib/mailchimp/member.rb +0 -15
  43. data/lib/mailchimp/version.rb +0 -3
  44. data/lib/mailchimp.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cea605da8196d54280fa8b3b52f804643720a4cc
4
- data.tar.gz: 9adf62426b975cf8f73e98a52f571a04fe335b57
3
+ metadata.gz: 84ec2a80c75ddcdd36c7096af5a44bced1e7104f
4
+ data.tar.gz: bac88f5b0e1e56d5a68f8e8efc35c08e43799198
5
5
  SHA512:
6
- metadata.gz: 5aa0078062716c9af0a986c84669a29eebc2cf982f5de986016b23a70a19e3aa6e19bcb3b8608fd254109f48614b736f86602183c8f24eab4086d77db5e9440b
7
- data.tar.gz: 5fc82ff959426f5d6ad832747301c6bdf536feeaf95d080645f2ef0b5c6c565a71268e7b5c3bed8f2764f2448f2e7bcc030954b3d7f88677380dc18b16811632
6
+ metadata.gz: f3154cb67c37dfe49e1b967174b159d6c5984737ef609a87876e4d070267d917b713b4622457f7808b7f9b7367d8cd1da3b1cc741317078731b89c6404ecbed9
7
+ data.tar.gz: f8bb921863f744878b8b875f8e046beae6a9d9e2e51055b1ac54e8293440497544cb470c9747a1e3c6edfd299253deee726ff696c7282bbfbcdd9f3fc505fb53
data/README.md CHANGED
@@ -1,13 +1,19 @@
1
1
  ## Mailchimp API v3
2
2
 
3
- ![Gem Version(https://rubygems.org/gems/mailchimp_api_v3)](http://img.shields.io/gem/v/mailchimp_api_v3.svg?style=flat)
4
- ![build status(https://circleci.com/gh/Xenapto/mailchimp_api_v3)](https://img.shields.io/circleci/project/Xenapto/mailchimp_api_v3/develop.svg)
5
- [![Code Climate](http://img.shields.io/codeclimate/github/Xenapto/mailchimp_api_v3.svg?style=flat)](https://codeclimate.com/github/Xenapto/mailchimp_api_v3)
6
- [![Coverage Status](https://img.shields.io/coveralls/Xenapto/mailchimp_api_v3/develop.svg?style=flat)](https://coveralls.io/r/Xenapto/mailchimp_api_v3?branch=develop)
7
- [![Developer status](http://img.shields.io/badge/developer-awesome-brightgreen.svg?style=flat)](http://xenapto.com)
3
+ [![](http://img.shields.io/gem/v/mailchimp_api_v3.svg?style=flat)](https://rubygems.org/gems/mailchimp_api_v3)
4
+ [![](https://img.shields.io/circleci/project/Xenapto/mailchimp_api_v3/develop.svg)](https://circleci.com/gh/Xenapto/mailchimp_api_v3)
5
+ [![](http://img.shields.io/codeclimate/github/Xenapto/mailchimp_api_v3.svg?style=flat)](https://codeclimate.com/github/Xenapto/mailchimp_api_v3)
6
+ [![](https://img.shields.io/coveralls/Xenapto/mailchimp_api_v3/develop.svg?style=flat)](https://coveralls.io/r/Xenapto/mailchimp_api_v3?branch=develop)
7
+ [![](http://img.shields.io/badge/developer-awesome-brightgreen.svg?style=flat)](http://xenapto.com)
8
8
 
9
9
  A simple gem to interact with Mailchimp through their API v3
10
10
 
11
+ ### Project status
12
+
13
+ This gem currently does everything I need for my project but it is far from complete. I will willingly accept good quality pull requests to complete the feature set.
14
+
15
+ My own requirements are for subscription management for my mailing list, so the gem can add and remove members from a list and manage their interests.
16
+
11
17
  ### Installation
12
18
 
13
19
  Add this line to your application's Gemfile:
@@ -24,10 +30,30 @@ Or install it yourself as:
24
30
 
25
31
  ### Usage
26
32
 
33
+ The Mailchimp API documentation is here: http://kb.mailchimp.com/api. Their suggstions for subscriber management are here: http://kb.mailchimp.com/api/article/how-to-manage-subscribers.
34
+
35
+ To connect to the Mailchimp API you need to supply an API key. You can do this explicitly when you connect, or you can set an environment variable `MAILCHIMP_API_KEY`.
36
+
27
37
  Examples:
28
38
 
29
39
  ```ruby
30
- Mailchimp.connect(mc_key).lists
40
+ MailchimpAPIV3.connect(my_api_key) # Uses the API key in my_api_key
41
+ MailchimpAPIV3.connect # Uses ENV['MAILCHIMP_API_KEY']
42
+ ```
43
+
44
+ ```ruby
45
+ MailchimpAPIV3.connect.lists
46
+ ```
47
+
48
+ ```ruby
49
+ mailchimp = MailchimpAPIV3.connect
50
+ list = mailchimp.lists.find_by name: 'My first list'
51
+ ```
52
+
53
+ ```ruby
54
+ mailchimp = MailchimpAPIV3.connect
55
+ member = mailchimp.lists('e73f5910ca').members('ann@example.com')
56
+ member.name # => "Ann Example"
31
57
  ```
32
58
 
33
59
  ### Contributing
@@ -38,6 +64,12 @@ Mailchimp.connect(mc_key).lists
38
64
  1. Push to the branch (`git push origin my-new-feature`)
39
65
  1. Create new Pull Request
40
66
 
67
+ ### Testing
68
+
69
+ The tests use Rspec and VCR. To avoid including my test API key in the VCR cassettes the tests use Erb to insert an api key at runtime. Whatever API key is available will allow the tests to pass.
70
+
71
+ If you need to add more cassettes you can use your own test API key then edit the VCR cassette in the same way before you issue the pull request.
72
+
41
73
  ### Acknowledgements
42
74
 
43
75
  I used the sample code in https://github.com/mailchimp/APIv3-examples as my starting point for this gem. Thanks to
data/circle.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ notify:
3
+ webhooks:
4
+ # A list of hook hashes, containing the url field
5
+ - url: https://coveralls.io/webhook?repo_token=SFdYC8cgEnwclAC8K7dzccQ5e16ZBDlPj
@@ -1,7 +1,6 @@
1
- module Mailchimp
1
+ module MailchimpAPIV3
2
2
  class Account
3
- PATH_KEY = DATA_KEY = ''
4
- include Instance
3
+ include Instance::InstanceMethods
5
4
 
6
5
  def id
7
6
  account_id
@@ -1,7 +1,7 @@
1
1
  require 'yaml'
2
2
  require 'restclient'
3
3
 
4
- module Mailchimp
4
+ module MailchimpAPIV3
5
5
  class Client
6
6
  module Remote
7
7
  def get(path = '', options = {})
@@ -22,9 +22,7 @@ module Mailchimp
22
22
 
23
23
  def managed_remote(path = '', options = {}, method = :get, payload = nil)
24
24
  headers_and_params = headers.merge params_from(options)
25
- url = "#{url_stub}#{path}"
26
- # puts url # debug
27
- YAML.load naked_remote(url, method, headers_and_params, payload)
25
+ YAML.load naked_remote("#{url_stub}#{path}", method, headers_and_params, payload)
28
26
  rescue *RETRY_EXCEPTIONS => e
29
27
  @retries ||= 0
30
28
  raise e if (@retries += 1) > 3
@@ -36,15 +34,16 @@ module Mailchimp
36
34
  def managed_remote_exception(e)
37
35
  case e.class.to_s # TODO: Find out why this won't match the class except by name string
38
36
  when 'RestClient::Unauthorized'
39
- fail Mailchimp::Exception::APIKeyError, YAML.load(e.http_body)
37
+ fail MailchimpAPIV3::Exception::APIKeyError, YAML.load(e.http_body)
40
38
  when 'RestClient::BadRequest'
41
- Mailchimp::Exception.parse_invalid_resource_exception YAML.load(e.http_body)
39
+ MailchimpAPIV3::Exception.parse_invalid_resource_exception YAML.load(e.http_body)
42
40
  else
43
41
  fail e
44
42
  end
45
43
  end
46
44
 
47
45
  def naked_remote(url, method, headers_and_params, payload = nil)
46
+ # puts url # debug
48
47
  if [:get, :delete, :head, :options].include? method
49
48
  remote_no_payload(url, method, headers_and_params)
50
49
  else
@@ -1,11 +1,11 @@
1
- require 'mailchimp/exception'
2
- require 'mailchimp/collection'
3
- require 'mailchimp/instance'
4
- require 'mailchimp/account'
5
- require 'mailchimp/lists'
6
- require 'mailchimp/client/remote'
7
-
8
- module Mailchimp
1
+ require 'mailchimp_api_v3/exception'
2
+ require 'mailchimp_api_v3/collection'
3
+ require 'mailchimp_api_v3/instance'
4
+ require 'mailchimp_api_v3/account'
5
+ require 'mailchimp_api_v3/lists'
6
+ require 'mailchimp_api_v3/client/remote'
7
+
8
+ module MailchimpAPIV3
9
9
  class Client
10
10
  include Remote
11
11
 
@@ -19,7 +19,7 @@ module Mailchimp
19
19
 
20
20
  def connected?
21
21
  account
22
- rescue Mailchimp::Exception::APIKeyError
22
+ rescue MailchimpAPIV3::Exception::APIKeyError
23
23
  false
24
24
  else
25
25
  true
@@ -29,7 +29,12 @@ module Mailchimp
29
29
 
30
30
  def initialize(api_key = nil, extra_headers = {})
31
31
  @api_key = api_key || ENV['MAILCHIMP_API_KEY']
32
- fail Mailchimp::Exception::APIKeyError, 'title' => 'Invalid API key format' unless api_key_valid?
32
+
33
+ fail(
34
+ MailchimpAPIV3::Exception::APIKeyError,
35
+ 'title' => "Invalid API key format: #{@api_key}"
36
+ ) unless api_key_valid?
37
+
33
38
  @extra_headers = extra_headers
34
39
  end
35
40
 
@@ -1,4 +1,4 @@
1
- module Mailchimp
1
+ module MailchimpAPIV3
2
2
  module Collection
3
3
  module Paging
4
4
  DEFAULT_PAGE_SIZE = 500
@@ -1,6 +1,6 @@
1
- require 'mailchimp/collection/paging'
1
+ require 'mailchimp_api_v3/collection/paging'
2
2
 
3
- module Mailchimp
3
+ module MailchimpAPIV3
4
4
  module Collection
5
5
  include Paging
6
6
 
@@ -20,15 +20,22 @@ module Mailchimp
20
20
  @path ||= "#{@parent_path}/#{self.class.path_key}"
21
21
  end
22
22
 
23
- def find(data)
23
+ def where(data, limit = nil)
24
+ instances = []
25
+
24
26
  find_each do |instance|
25
- matches = data.each do |k, v|
26
- break false unless instance.__send__(k).casecmp(v).zero? # case-insensitive comparison
27
- true
27
+ if instance.matches? data
28
+ instances << instance
29
+ break if instances.count == limit
28
30
  end
29
-
30
- break instance if matches
31
31
  end
32
+
33
+ instances
34
+ end
35
+
36
+ def find_by(data)
37
+ instances = where(data, 1)
38
+ instances ? instances.first : nil
32
39
  end
33
40
 
34
41
  def create(data)
@@ -37,7 +44,7 @@ module Mailchimp
37
44
  end
38
45
 
39
46
  def first_or_create(data)
40
- instance = find(data)
47
+ instance = find_by(data)
41
48
  return instance if instance
42
49
  create(data)
43
50
  end
@@ -1,14 +1,18 @@
1
- module Mailchimp
1
+ module MailchimpAPIV3
2
2
  module Exception
3
3
  def self.parse_invalid_resource_exception(data)
4
- if data['detail'].include? 'already exists'
4
+ detail = data['detail']
5
+
6
+ if detail.include? 'already exists'
5
7
  fail Duplicate, data
8
+ elsif detail.include? 'can\'t be blank'
9
+ fail MissingField, data
6
10
  else
7
11
  fail BadRequest, data
8
12
  end
9
13
  end
10
14
 
11
- module DataException
15
+ class DataException < RuntimeError
12
16
  def initialize(data)
13
17
  @data = data
14
18
  super name || title
@@ -19,16 +23,16 @@ module Mailchimp
19
23
  end
20
24
  end
21
25
 
22
- class APIKeyError < RuntimeError
23
- include DataException
26
+ class APIKeyError < DataException
27
+ end
28
+
29
+ class Duplicate < DataException
24
30
  end
25
31
 
26
- class Duplicate < RuntimeError
27
- include DataException
32
+ class MissingField < DataException
28
33
  end
29
34
 
30
- class BadRequest < RuntimeError
31
- include DataException
35
+ class BadRequest < DataException
32
36
  end
33
37
 
34
38
  class UnknownAttribute < RuntimeError
@@ -0,0 +1,62 @@
1
+ module MailchimpAPIV3
2
+ module Instance
3
+ module InstanceMethods
4
+ def initialize(client, data, collection_path = '')
5
+ @client = client
6
+ @collection_path = collection_path
7
+ @data = data
8
+ #- puts @data # debug
9
+ end
10
+
11
+ def update(new_data)
12
+ @data = @client.patch(new_data, path)
13
+ self
14
+ end
15
+
16
+ def path
17
+ @path ||= "#{@collection_path}/#{@data['id']}"
18
+ end
19
+
20
+ def matches?(match_data)
21
+ match_data.each do |k, v|
22
+ break false unless __send__(k).casecmp(v).zero? # case-insensitive comparison
23
+ true
24
+ end
25
+ end
26
+
27
+ def subclass_from(collection_class, options = {})
28
+ if options.is_a? String
29
+ # Use it as an id for an instance
30
+ child_path = "#{path}/#{collection_class.path_key}"
31
+ collection_class.child_class.get @client, child_path, options
32
+ else
33
+ # Get the collection
34
+ collection_class.new @client, path, options
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :data
41
+
42
+ def method_missing(symbol, options = {})
43
+ key = symbol.id2name
44
+ fail_unless_exists key, options
45
+ @data[key]
46
+ end
47
+
48
+ def fail_unless_exists(key, options = {})
49
+ return if @data.key? key
50
+ message = options == {} ? key : "#{key}: #{options}"
51
+ fail MailchimpAPIV3::Exception::UnknownAttribute, message
52
+ end
53
+ end
54
+
55
+ module ClassMethods
56
+ def get(client, collection_path, id)
57
+ data = client.get "#{collection_path}/#{id}"
58
+ new client, data, collection_path
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,10 @@
1
+ module MailchimpAPIV3
2
+ class List
3
+ class InterestCategory
4
+ class Interest
5
+ include Instance::InstanceMethods
6
+ extend Instance::ClassMethods
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,8 +1,10 @@
1
- require 'mailchimp/interest_category'
1
+ require 'mailchimp_api_v3/interest_category'
2
2
 
3
- module Mailchimp
3
+ module MailchimpAPIV3
4
4
  class List
5
5
  class InterestCategories < Array
6
+ include Collection
7
+
6
8
  class << self
7
9
  def path_key
8
10
  'interest-categories'
@@ -16,8 +18,6 @@ module Mailchimp
16
18
  InterestCategory
17
19
  end
18
20
  end
19
-
20
- include Collection
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,16 @@
1
+ require 'mailchimp_api_v3/interests'
2
+
3
+ module MailchimpAPIV3
4
+ class List
5
+ class InterestCategory
6
+ #- VALID_TYPES = %w(checkboxes dropdown radio hidden)
7
+
8
+ include Instance::InstanceMethods
9
+ extend Instance::ClassMethods
10
+
11
+ def interests(options = {})
12
+ subclass_from Interests, options
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,9 +1,11 @@
1
- require 'mailchimp/interest'
1
+ require 'mailchimp_api_v3/interest'
2
2
 
3
- module Mailchimp
3
+ module MailchimpAPIV3
4
4
  class List
5
5
  class InterestCategory
6
6
  class Interests < Array
7
+ include Collection
8
+
7
9
  class << self
8
10
  def path_key
9
11
  'interests'
@@ -17,8 +19,6 @@ module Mailchimp
17
19
  Interest
18
20
  end
19
21
  end
20
-
21
- include Collection
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,26 @@
1
+ require 'mailchimp_api_v3/members'
2
+ require 'mailchimp_api_v3/interest_categories'
3
+
4
+ module MailchimpAPIV3
5
+ class List
6
+ include Instance::InstanceMethods
7
+ extend Instance::ClassMethods
8
+
9
+ def members(options = {})
10
+ # Turn an email into an id
11
+ if options.is_a?(String) && (options =~ /\A[^@]+@[^@]+\z/)
12
+ options = OpenSSL::Digest.digest('MD5', options).unpack('H*').first
13
+ end
14
+
15
+ subclass_from Members, options
16
+ end
17
+
18
+ def interest_categories(options = {})
19
+ subclass_from InterestCategories, options
20
+ end
21
+
22
+ def id_and_name
23
+ "#{id}___#{name}"
24
+ end
25
+ end
26
+ end
@@ -1,7 +1,9 @@
1
- require 'mailchimp/list'
1
+ require 'mailchimp_api_v3/list'
2
2
 
3
- module Mailchimp
3
+ module MailchimpAPIV3
4
4
  class Lists < Array
5
+ include Collection
6
+
5
7
  class << self
6
8
  def path_key
7
9
  'lists'
@@ -15,7 +17,5 @@ module Mailchimp
15
17
  List
16
18
  end
17
19
  end
18
-
19
- include Collection
20
20
  end
21
21
  end
@@ -0,0 +1,55 @@
1
+ module MailchimpAPIV3
2
+ class List
3
+ class Member
4
+ include Instance::InstanceMethods
5
+ extend Instance::ClassMethods
6
+
7
+ def first_name
8
+ @first_name ||= merge_fields['FNAME']
9
+ end
10
+
11
+ def last_name
12
+ @last_name ||= merge_fields['LNAME']
13
+ end
14
+
15
+ def name
16
+ return @name if @name
17
+ delim = first_name && last_name ? ' ' : ''
18
+ @name = "#{first_name}#{delim}#{last_name}"
19
+ end
20
+
21
+ def update(new_data)
22
+ invalidate_derived_fields
23
+ super parse_name_from(new_data)
24
+ end
25
+
26
+ private
27
+
28
+ def invalidate_derived_fields
29
+ @first_name = @last_name = @name = nil
30
+ end
31
+
32
+ def parse_name_from(new_data)
33
+ clean_data = new_data.deep_stringify_keys
34
+ fname, lname = name_parts_from clean_data
35
+
36
+ merge_fields = {}
37
+ merge_fields['FNAME'] = fname if fname
38
+ merge_fields['LNAME'] = lname if lname
39
+ additional_data = merge_fields.empty? ? {} : { 'merge_fields' => merge_fields }
40
+
41
+ additional_data.merge clean_data
42
+ end
43
+
44
+ def name_parts_from(clean_data)
45
+ new_name = clean_data.delete('name')
46
+ name_parts = new_name ? new_name.split : []
47
+
48
+ [
49
+ clean_data.delete('first_name') || name_parts[0],
50
+ clean_data.delete('last_name') || name_parts[1]
51
+ ]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,8 +1,10 @@
1
- require 'mailchimp/member'
1
+ require 'mailchimp_api_v3/member'
2
2
 
3
- module Mailchimp
3
+ module MailchimpAPIV3
4
4
  class List
5
5
  class Members < Array
6
+ include Collection
7
+
6
8
  class << self
7
9
  def path_key
8
10
  'members'
@@ -16,8 +18,6 @@ module Mailchimp
16
18
  Member
17
19
  end
18
20
  end
19
-
20
- include Collection
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,3 @@
1
+ module MailchimpAPIV3
2
+ VERSION = '0.0.4'
3
+ end
@@ -1,14 +1,14 @@
1
1
  lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'mailchimp/version'
3
+ require 'mailchimp_api_v3/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'mailchimp_api_v3'
7
- spec.version = Mailchimp::VERSION
7
+ spec.version = MailchimpAPIV3::VERSION
8
8
  spec.authors = ['Xenapto']
9
9
  spec.email = ['developers@xenapto.com']
10
10
  spec.description = 'A simple gem to interact with Mailchimp through their API v3'
11
- spec.summary = 'Example: Mailchimp.new(mc_key).lists'
11
+ spec.summary = 'Example: mailchimp.lists("My first list").member("ann@example.com")'
12
12
  spec.homepage = 'https://github.com/Xenapto/mailchimp_api_v3'
13
13
  spec.license = 'BSD'
14
14
 
@@ -17,9 +17,9 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features|coverage)\/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
- spec.add_runtime_dependency 'rest-client', '> 1.6'
20
+ spec.add_runtime_dependency 'rest-client', '~> 1.6', '> 1.6'
21
21
 
22
- spec.add_development_dependency 'bundler', '> 1.8'
22
+ spec.add_development_dependency 'bundler', '~> 1.8', '> 1.8'
23
23
  spec.add_development_dependency 'rspec', '~> 3.3'
24
24
  spec.add_development_dependency 'rspec_junit_formatter', '~> 0.2'
25
25
  spec.add_development_dependency 'gem-release', '~> 0.7'