notion-ruby-client 0.0.8 → 1.0.0.pre.beta2

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +5 -0
  3. data/.devcontainer/boot.sh +1 -0
  4. data/.devcontainer/devcontainer.json +30 -0
  5. data/.github/workflows/ci.yml +1 -0
  6. data/.gitignore +7 -0
  7. data/.rubocop.yml +9 -0
  8. data/CHANGELOG.md +43 -0
  9. data/CONTRIBUTING.md +51 -0
  10. data/Gemfile.lock +38 -11
  11. data/README.md +354 -108
  12. data/bin/console +31 -0
  13. data/lib/notion/api/endpoints/blocks.rb +51 -7
  14. data/lib/notion/api/endpoints/databases.rb +60 -53
  15. data/lib/notion/api/endpoints/pages.rb +24 -7
  16. data/lib/notion/api/endpoints/search.rb +41 -0
  17. data/lib/notion/api/endpoints/users.rb +14 -3
  18. data/lib/notion/api/endpoints.rb +3 -1
  19. data/lib/notion/api/errors/too_many_requests.rb +15 -0
  20. data/lib/notion/api/errors.rb +0 -2
  21. data/lib/notion/config.rb +2 -0
  22. data/lib/notion/pagination/cursor.rb +5 -2
  23. data/lib/notion/version.rb +2 -2
  24. data/lib/notion-ruby-client.rb +2 -0
  25. data/notion-ruby-client.gemspec +5 -3
  26. data/spec/fixtures/notion/block.yml +146 -0
  27. data/spec/fixtures/notion/block_append_children.yml +76 -62
  28. data/spec/fixtures/notion/block_children.yml +80 -65
  29. data/spec/fixtures/notion/create_database.yml +67 -58
  30. data/spec/fixtures/notion/create_page.yml +68 -59
  31. data/spec/fixtures/notion/database.yml +78 -61
  32. data/spec/fixtures/notion/database_query.yml +81 -62
  33. data/spec/fixtures/notion/delete_block.yml +145 -0
  34. data/spec/fixtures/notion/page.yml +70 -57
  35. data/spec/fixtures/notion/page_property_item.yml +143 -0
  36. data/spec/fixtures/notion/paginated_block_children.yml +296 -242
  37. data/spec/fixtures/notion/paginated_database_query.yml +79 -62
  38. data/spec/fixtures/notion/paginated_databases_list.yml +78 -61
  39. data/spec/fixtures/notion/paginated_search.yml +301 -0
  40. data/spec/fixtures/notion/paginated_users_list.yml +143 -130
  41. data/spec/fixtures/notion/search.yml +160 -0
  42. data/spec/fixtures/notion/search_with_query.yml +152 -0
  43. data/spec/fixtures/notion/update_block.yml +148 -0
  44. data/spec/fixtures/notion/update_database.yml +152 -0
  45. data/spec/fixtures/notion/update_page.yml +71 -59
  46. data/spec/fixtures/notion/users.yml +69 -56
  47. data/spec/fixtures/notion/users_list.yml +143 -130
  48. data/spec/fixtures/notion/users_me.yml +144 -0
  49. data/spec/notion/api/endpoints/blocks_spec.rb +44 -12
  50. data/spec/notion/api/endpoints/databases_spec.rb +22 -27
  51. data/spec/notion/api/endpoints/pages_spec.rb +13 -16
  52. data/spec/notion/api/endpoints/search_spec.rb +26 -0
  53. data/spec/notion/api/endpoints/users_spec.rb +9 -4
  54. data/spec/notion/pagination/cursor_spec.rb +126 -0
  55. metadata +67 -15
  56. data/.rspec_status +0 -19
  57. data/notion-ruby-client-0.0.4.gem +0 -0
  58. data/scratchpad.rb +0 -22
  59. data/screenshots/create_notion_bot.png +0 -0
  60. data/spec/fixtures/notion/databases_list.yml +0 -133
@@ -4,6 +4,50 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Blocks
7
+ #
8
+ # Retrieves a Block object using the ID specified.
9
+ #
10
+ # @option options [id] :block_id
11
+ # Block to get children info on.
12
+ def block(options = {})
13
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
14
+ get("blocks/#{options[:block_id]}")
15
+ end
16
+
17
+ #
18
+ # Updates the content for the specified block_id based on
19
+ # the block type. Supported fields based on the block object
20
+ # type (see Block object for available fields and the
21
+ # expected input for each field).
22
+ #
23
+ # @option options [id] :block_id
24
+ # Block to get children info on.
25
+ #
26
+ # @option options [string] {type}
27
+ # The block object type value with the properties to be
28
+ # updated. Currently only text (for supported block types)
29
+ # and checked (for to_do blocks) fields can be updated.
30
+ def update_block(options = {})
31
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
32
+ patch("blocks/#{options[:block_id]}", options.except(:block_id))
33
+ end
34
+
35
+ #
36
+ # Sets a Block object, including page blocks, to archived: true
37
+ # using the ID specified. Note: in the Notion UI application, this
38
+ # moves the block to the "Trash" where it can still be accessed and
39
+ # restored.
40
+ #
41
+ # To restore the block with the API, use the Update a block or
42
+ # Update page respectively.
43
+ #
44
+ # @option options [id] :block_id
45
+ # Block to get children info on.
46
+ def delete_block(options = {})
47
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
48
+ delete("blocks/#{options[:block_id]}")
49
+ end
50
+
7
51
  #
8
52
  # Returns a paginated array of Block objects contained in the
9
53
  # block of the requested path using the ID specified.
@@ -14,16 +58,16 @@ module Notion
14
58
  #
15
59
  # Returns a 400 or 429 HTTP response if the request exceeds Notion's Request limits.
16
60
  #
17
- # @option options [id] :id
61
+ # @option options [id] :block_id
18
62
  # Block to get children info on.
19
63
  def block_children(options = {})
20
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
64
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
21
65
  if block_given?
22
66
  Pagination::Cursor.new(self, :block_children, options).each do |page|
23
67
  yield page
24
68
  end
25
69
  else
26
- get("blocks/#{options[:id]}/children", options)
70
+ get("blocks/#{options[:block_id]}/children", options.except(:block_id))
27
71
  end
28
72
  end
29
73
 
@@ -38,14 +82,14 @@ module Notion
38
82
  #
39
83
  # Returns a 400 or 429 HTTP response if the request exceeds Notion's Request limits.
40
84
  #
41
- # @option options [id] :id
42
- # Block to get children info on.
85
+ # @option options [id] :block_id
86
+ # Block to append children to.
43
87
  #
44
88
  # @option options [[Object]] :children
45
89
  # Children blocks to append
46
90
  def block_append_children(options = {})
47
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
48
- patch("blocks/#{options[:id]}/children", options)
91
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
92
+ patch("blocks/#{options[:block_id]}/children", options.except(:block_id))
49
93
  end
50
94
  end
51
95
  end
@@ -4,42 +4,6 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Databases
7
- #
8
- # Retrieves a Database object using the ID specified in the request.
9
- #
10
- # Returns a 404 HTTP response if the database doesn't exist, or if the bot
11
- # doesn't have access to the database. Returns a 429 HTTP response if the
12
- # request exceeds Notion's Request limits.
13
- #
14
- # @option options [id] :id
15
- # Database to get info on.
16
- def database(options = {})
17
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
18
- get("databases/#{options[:id]}")
19
- end
20
-
21
- #
22
- # Creates a new database in the specified page.
23
- #
24
- # @option options [Object] :parent
25
- # Parent of the database, which is always going to be a page.
26
- #
27
- # @option options [Object] :title
28
- # Title of this database.
29
- #
30
- # @option options [Object] :properties
31
- # Property schema of database.
32
- # The keys are the names of properties as they appear in Notion and the values are
33
- # property schema objects. Property Schema Object is a metadata that controls
34
- # how a database property behaves, e.g. {"checkbox": {}}.
35
- # Each database must have exactly one database property schema object of type "title".
36
- def create_database(options = {})
37
- throw ArgumentError.new('Required arguments :parent.page_id missing') if options.dig(:parent, :page_id).nil?
38
- throw ArgumentError.new('Required arguments :title missing') if options.dig(:title).nil?
39
- throw ArgumentError.new('Required arguments :properties missing') if options.dig(:properties).nil?
40
- post('databases', options)
41
- end
42
-
43
7
  #
44
8
  # Gets a paginated array of Page object s contained in the requested database,
45
9
  # filtered and ordered according to the filter and sort objects provided in the request.
@@ -52,7 +16,7 @@ module Notion
52
16
  # database properties and can be combined. The order of the sorts in the request
53
17
  # matter, with earlier sorts taking precedence over later ones.
54
18
  #
55
- # @option options [id] :id
19
+ # @option options [id] :database_id
56
20
  # Database to query.
57
21
  #
58
22
  # @option options [Object] :filter
@@ -66,33 +30,76 @@ module Notion
66
30
  # to a start_cursor attribute returned by a previous request's next_cursor.
67
31
  # Default value fetches the first "page" of the collection.
68
32
  # See pagination for more detail.
33
+ #
34
+ # @option options [integer] :page_size
35
+ # The number of items from the full list desired in the response. Maximum: 100
69
36
  def database_query(options = {})
70
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
37
+ throw ArgumentError.new('Required arguments :database_id missing') if options[:database_id].nil?
71
38
  if block_given?
72
39
  Pagination::Cursor.new(self, :database_query, options).each do |page|
73
40
  yield page
74
41
  end
75
42
  else
76
- post("databases/#{options[:id]}/query", options)
43
+ post("databases/#{options[:database_id]}/query", options.except(:database_id))
77
44
  end
78
45
  end
79
46
 
80
47
  #
81
- # Returns a paginated list of Databases objects for the workspace.
48
+ # Creates a new database in the specified page.
82
49
  #
83
- # @option options [UUID] :start_cursor
84
- # Paginate through collections of data by setting the cursor parameter
85
- # to a start_cursor attribute returned by a previous request's next_cursor.
86
- # Default value fetches the first "page" of the collection.
87
- # See pagination for more detail.
88
- def databases_list(options = {})
89
- if block_given?
90
- Pagination::Cursor.new(self, :databases_list, options).each do |page|
91
- yield page
92
- end
93
- else
94
- get('databases', options)
95
- end
50
+ # @option options [Object] :parent
51
+ # Parent of the database, which is always going to be a page.
52
+ #
53
+ # @option options [Object] :title
54
+ # Title of this database.
55
+ #
56
+ # @option options [Object] :properties
57
+ # Property schema of database.
58
+ # The keys are the names of properties as they appear in Notion and the values are
59
+ # property schema objects. Property Schema Object is a metadata that controls
60
+ # how a database property behaves, e.g. {"checkbox": {}}.
61
+ # Each database must have exactly one database property schema object of type "title".
62
+ def create_database(options = {})
63
+ throw ArgumentError.new('Required arguments :parent.page_id missing') if options.dig(:parent, :page_id).nil?
64
+ throw ArgumentError.new('Required arguments :title missing') if options.dig(:title).nil?
65
+ throw ArgumentError.new('Required arguments :properties missing') if options.dig(:properties).nil?
66
+ post('databases', options)
67
+ end
68
+
69
+ #
70
+ # Updates an existing database as specified by the parameters.
71
+ #
72
+ # @option options [id] :database_id
73
+ # Database to update.
74
+ #
75
+ # @option options [Object] :title
76
+ # Title of database as it appears in Notion. An array of rich text objects.
77
+ # If omitted, the database title will remain unchanged.
78
+ #
79
+ # @option options [Object] :properties
80
+ # Updates to the property schema of a database.
81
+ # If updating an existing property, the keys are the names or IDs
82
+ # of the properties as they appear in Notion and the values
83
+ # are property schema objects. If adding a new property, the key is
84
+ # the name of the database property and the value is a property schema object.
85
+ #
86
+ def update_database(options = {})
87
+ throw ArgumentError.new('Required arguments :database_id missing') if options.dig(:database_id).nil?
88
+ patch("databases/#{options[:database_id]}", options.except(:database_id))
89
+ end
90
+
91
+ #
92
+ # Retrieves a Database object using the ID specified in the request.
93
+ #
94
+ # Returns a 404 HTTP response if the database doesn't exist, or if the bot
95
+ # doesn't have access to the database. Returns a 429 HTTP response if the
96
+ # request exceeds Notion's Request limits.
97
+ #
98
+ # @option options [id] :database_id
99
+ # Database to get info on.
100
+ def database(options = {})
101
+ throw ArgumentError.new('Required arguments :database_id missing') if options[:database_id].nil?
102
+ get("databases/#{options[:database_id]}")
96
103
  end
97
104
  end
98
105
  end
@@ -8,15 +8,15 @@ module Notion
8
8
  # Retrieves a 📄Page object using the ID specified in the request path.
9
9
  # Note that this version of the API only exposes page properties, not page content
10
10
  #
11
- # @option options [id] :id
11
+ # @option options [id] :page_id
12
12
  # Page to get info on.
13
13
  #
14
14
  # @option options [bool] :archived
15
15
  # Set to true to retrieve an archived page; must be false or omitted to
16
16
  # retrieve a page that has not been archived. Defaults to false.
17
17
  def page(options = {})
18
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
19
- get("pages/#{options[:id]}")
18
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
19
+ get("pages/#{options[:page_id]}")
20
20
  end
21
21
 
22
22
  #
@@ -38,7 +38,7 @@ module Notion
38
38
  # @option options [Object] :children
39
39
  # An optional array of Block objects representing the Page’s content
40
40
  def create_page(options = {})
41
- throw ArgumentError.new('Required arguments :parent.database_id missing') if options.dig(:parent, :database_id).nil?
41
+ throw ArgumentError.new('Required argument :parent.database_id missing') if options.dig(:parent, :database_id).nil?
42
42
  post("pages", options)
43
43
  end
44
44
 
@@ -50,7 +50,7 @@ module Notion
50
50
  # Note that this iteration of the API will only expose page properties, not page
51
51
  # content, as described in the data model.
52
52
  #
53
- # @option options [id] :id
53
+ # @option options [id] :page_id
54
54
  # Page to get info on.
55
55
  #
56
56
  # @option options [Object] :properties
@@ -60,8 +60,25 @@ module Notion
60
60
  # appears in Notion, or property ID. value object Object containing a value
61
61
  # specific to the property type, e.g. {"checkbox": true}.
62
62
  def update_page(options = {})
63
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
64
- patch("pages/#{options[:id]}", options)
63
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
64
+ patch("pages/#{options[:page_id]}", options.except(:page_id))
65
+ end
66
+
67
+ #
68
+ # Retrieves a `property_item` object for a given `page_id` and `property_id`.
69
+ # Depending on the property type, the object returned will either be a value
70
+ # or a paginated list of property item values.
71
+ #
72
+ # @option options [id] :page_id
73
+ # Page to get info on.
74
+ #
75
+ # @option options [id] :property_id
76
+ # Property to get info on.
77
+ #
78
+ def page_property_item(options = {})
79
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
80
+ throw ArgumentError.new('Required argument :property_id missing') if options[:property_id].nil?
81
+ get("pages/#{options[:page_id]}/properties/#{options[:property_id]}")
65
82
  end
66
83
  end
67
84
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Notion
4
+ module Api
5
+ module Endpoints
6
+ module Search
7
+ #
8
+ # Searches all pages and child pages that are shared with the integration.
9
+ # The results may include databases.
10
+ #
11
+ # @option options [string] :query
12
+ # When supplied, limits which pages are returned by comparing the query to the page title.
13
+ #
14
+ # @option options [Object] :filter
15
+ # When supplied, filters the results based on the provided criteria.
16
+ #
17
+ # @option options [[Object]] :sorts
18
+ # When supplied, sorts the results based on the provided criteria.
19
+ # Limitation: Currently only a single sort is allowed and is limited to last_edited_time.
20
+ #
21
+ # @option options [UUID] :start_cursor
22
+ # Paginate through collections of data by setting the cursor parameter
23
+ # to a start_cursor attribute returned by a previous request's next_cursor.
24
+ # Default value fetches the first "page" of the collection.
25
+ # See pagination for more detail.
26
+ #
27
+ # @option options [integer] :page_size
28
+ # The number of items from the full list desired in the response. Maximum: 100
29
+ def search(options = {})
30
+ if block_given?
31
+ Pagination::Cursor.new(self, :search, options).each do |page|
32
+ yield page
33
+ end
34
+ else
35
+ post('search', options)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,14 +4,22 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Users
7
+ #
8
+ # Retrieves the bot User associated with the API token provided in
9
+ # the authorization header. The bot will have an `owner` field with
10
+ # information about the person who authorized the integration.
11
+ def me
12
+ get("users/me")
13
+ end
14
+
7
15
  #
8
16
  # Retrieves a User object using the ID specified in the request.
9
17
  #
10
- # @option options [id] :id
18
+ # @option options [id] :user_id
11
19
  # User to get info on.
12
20
  def user(options = {})
13
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
14
- get("users/#{options[:id]}")
21
+ throw ArgumentError.new('Required arguments :user_id missing') if options[:user_id].nil?
22
+ get("users/#{options[:user_id]}")
15
23
  end
16
24
 
17
25
  #
@@ -22,6 +30,9 @@ module Notion
22
30
  # to a start_cursor attribute returned by a previous request's next_cursor.
23
31
  # Default value fetches the first "page" of the collection.
24
32
  # See pagination for more detail.
33
+ #
34
+ # @option options [integer] :page_size
35
+ # The number of items from the full list desired in the response. Maximum: 100
25
36
  def users_list(options = {})
26
37
  if block_given?
27
38
  Pagination::Cursor.new(self, :users_list, options).each do |page|
@@ -4,6 +4,7 @@ require_relative 'endpoints/blocks'
4
4
  require_relative 'endpoints/databases'
5
5
  require_relative 'endpoints/pages'
6
6
  require_relative 'endpoints/users'
7
+ require_relative 'endpoints/search'
7
8
 
8
9
  module Notion
9
10
  module Api
@@ -12,6 +13,7 @@ module Notion
12
13
  include Databases
13
14
  include Pages
14
15
  include Users
16
+ include Search
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Notion
3
+ module Api
4
+ module Errors
5
+ class TooManyRequests < ::Faraday::Error
6
+ attr_reader :response
7
+
8
+ def initialize(response)
9
+ @response = response
10
+ super 'Too many requests'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,7 +8,6 @@ module Notion
8
8
  class InternalError < NotionError; end
9
9
  class InvalidRequest < NotionError; end
10
10
  class ObjectNotFound < NotionError; end
11
- class TooManyRequests < NotionError; end
12
11
  class Unauthorized < NotionError; end
13
12
 
14
13
  ERROR_CLASSES = {
@@ -17,7 +16,6 @@ module Notion
17
16
  'internal_error' => InternalError,
18
17
  'invalid_request' => InvalidRequest,
19
18
  'object_not_found' => ObjectNotFound,
20
- 'rate_limited' => TooManyRequests,
21
19
  'unauthorized' => Unauthorized
22
20
  }.freeze
23
21
  end
data/lib/notion/config.rb CHANGED
@@ -15,6 +15,7 @@ module Notion
15
15
  open_timeout
16
16
  default_page_size
17
17
  default_max_retries
18
+ default_retry_after
18
19
  adapter
19
20
  ].freeze
20
21
 
@@ -32,6 +33,7 @@ module Notion
32
33
  self.open_timeout = nil
33
34
  self.default_page_size = 100
34
35
  self.default_max_retries = 100
36
+ self.default_retry_after = 10
35
37
  self.adapter = ::Faraday.default_adapter
36
38
  end
37
39
 
@@ -9,6 +9,7 @@ module Notion
9
9
  attr_reader :verb
10
10
  attr_reader :sleep_interval
11
11
  attr_reader :max_retries
12
+ attr_reader :retry_after
12
13
  attr_reader :params
13
14
 
14
15
  def initialize(client, verb, params = {})
@@ -17,13 +18,15 @@ module Notion
17
18
  @params = params.dup
18
19
  @sleep_interval = @params.delete(:sleep_interval)
19
20
  @max_retries = @params.delete(:max_retries) || client.default_max_retries
21
+ @retry_after = @params.delete(:retry_after) || client.default_retry_after
20
22
  end
21
23
 
22
24
  def each
23
25
  next_cursor = nil
24
26
  retry_count = 0
25
27
  loop do
26
- query = next_cursor.nil? ? params : params.merge(start_cursor: next_cursor)
28
+ query = { page_size: client.default_page_size }.merge(params)
29
+ query = query.merge(start_cursor: next_cursor) unless next_cursor.nil?
27
30
  begin
28
31
  response = client.send(verb, query)
29
32
  rescue Notion::Api::Errors::TooManyRequests => e
@@ -31,7 +34,7 @@ module Notion
31
34
 
32
35
  client.logger.debug("#{self.class}##{__method__}") { e.to_s }
33
36
  retry_count += 1
34
- sleep(e.retry_after)
37
+ sleep(retry_after)
35
38
  next
36
39
  end
37
40
  yield response
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Notion
3
- VERSION = '0.0.8'
4
- NOTION_REQUEST_VERSION = '2021-05-13'
3
+ VERSION = '1.0.0-beta2'
4
+ NOTION_REQUEST_VERSION = '2022-02-22'
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'active_support/core_ext/hash/except'
2
3
  require 'faraday'
3
4
  require 'faraday_middleware'
4
5
  require 'json'
@@ -17,6 +18,7 @@ require_relative 'notion/api/errors/notion_error'
17
18
  require_relative 'notion/api/error'
18
19
  require_relative 'notion/api/errors'
19
20
  require_relative 'notion/api/errors/internal_error'
21
+ require_relative 'notion/api/errors/too_many_requests'
20
22
  require_relative 'notion/faraday/response/raise_error'
21
23
  require_relative 'notion/faraday/response/wrap_error'
22
24
  require_relative 'notion/faraday/connection'
@@ -15,10 +15,12 @@ Gem::Specification.new do |s|
15
15
  s.homepage = 'http://github.com/orbit-love/notion-ruby-client'
16
16
  s.licenses = ['MIT']
17
17
  s.summary = 'Notion API client for Ruby.'
18
+ s.add_dependency 'activesupport', '>= 6'
19
+ s.add_dependency 'dotenv'
18
20
  s.add_dependency 'faraday', '>= 1.0'
19
21
  s.add_dependency 'faraday_middleware'
20
- s.add_dependency 'hashie'
21
- s.add_development_dependency 'rake', '~> 10'
22
+ s.add_dependency 'hashie', '~> 5'
23
+ s.add_development_dependency 'rake', '~> 13'
22
24
  s.add_development_dependency 'rspec'
23
25
  s.add_development_dependency 'rubocop', '~> 0.82.0'
24
26
  s.add_development_dependency 'rubocop-performance', '~> 1.5.2'
@@ -26,4 +28,4 @@ Gem::Specification.new do |s|
26
28
  s.add_development_dependency 'timecop'
27
29
  s.add_development_dependency 'vcr'
28
30
  s.add_development_dependency 'webmock'
29
- end
31
+ end