ruby-lokalise-api 2.10.0 → 3.0.0

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODE_OF_CONDUCT.md +1 -1
  3. data/.github/CONTRIBUTING.md +2 -2
  4. data/CHANGELOG.md +23 -0
  5. data/README.md +275 -180
  6. data/lib/ruby-lokalise-api.rb +2 -0
  7. data/lib/ruby-lokalise-api/client.rb +1 -0
  8. data/lib/ruby-lokalise-api/collections/base.rb +3 -2
  9. data/lib/ruby-lokalise-api/collections/queued_process.rb +15 -0
  10. data/lib/ruby-lokalise-api/data/attributes.json +12 -1
  11. data/lib/ruby-lokalise-api/resources/base.rb +33 -17
  12. data/lib/ruby-lokalise-api/resources/branch.rb +1 -1
  13. data/lib/ruby-lokalise-api/resources/contributor.rb +1 -1
  14. data/lib/ruby-lokalise-api/resources/custom_translation_status.rb +1 -1
  15. data/lib/ruby-lokalise-api/resources/file.rb +4 -1
  16. data/lib/ruby-lokalise-api/resources/key.rb +1 -1
  17. data/lib/ruby-lokalise-api/resources/key_comment.rb +1 -1
  18. data/lib/ruby-lokalise-api/resources/order.rb +2 -0
  19. data/lib/ruby-lokalise-api/resources/payment_card.rb +1 -1
  20. data/lib/ruby-lokalise-api/resources/project.rb +1 -1
  21. data/lib/ruby-lokalise-api/resources/queued_process.rb +18 -0
  22. data/lib/ruby-lokalise-api/resources/screenshot.rb +1 -1
  23. data/lib/ruby-lokalise-api/resources/snapshot.rb +3 -1
  24. data/lib/ruby-lokalise-api/resources/task.rb +1 -1
  25. data/lib/ruby-lokalise-api/resources/team_user.rb +1 -1
  26. data/lib/ruby-lokalise-api/resources/translation.rb +1 -1
  27. data/lib/ruby-lokalise-api/resources/webhook.rb +1 -1
  28. data/lib/ruby-lokalise-api/rest/comments.rb +5 -5
  29. data/lib/ruby-lokalise-api/rest/contributors.rb +5 -5
  30. data/lib/ruby-lokalise-api/rest/custom_translation_statuses.rb +6 -6
  31. data/lib/ruby-lokalise-api/rest/files.rb +3 -3
  32. data/lib/ruby-lokalise-api/rest/keys.rb +7 -7
  33. data/lib/ruby-lokalise-api/rest/languages.rb +6 -6
  34. data/lib/ruby-lokalise-api/rest/payment_cards.rb +3 -3
  35. data/lib/ruby-lokalise-api/rest/projects.rb +6 -6
  36. data/lib/ruby-lokalise-api/rest/queued_processes.rb +26 -0
  37. data/lib/ruby-lokalise-api/rest/screenshots.rb +5 -5
  38. data/lib/ruby-lokalise-api/rest/snapshots.rb +4 -4
  39. data/lib/ruby-lokalise-api/rest/tasks.rb +5 -5
  40. data/lib/ruby-lokalise-api/rest/team_users.rb +4 -4
  41. data/lib/ruby-lokalise-api/rest/teams.rb +1 -1
  42. data/lib/ruby-lokalise-api/rest/translation_providers.rb +2 -2
  43. data/lib/ruby-lokalise-api/rest/translations.rb +3 -3
  44. data/lib/ruby-lokalise-api/rest/webhooks.rb +5 -5
  45. data/lib/ruby-lokalise-api/version.rb +1 -1
  46. data/ruby-lokalise-api.gemspec +1 -2
  47. data/spec/lib/ruby-lokalise-api/error_spec.rb +8 -0
  48. data/spec/lib/ruby-lokalise-api/rest/branches_spec.rb +12 -0
  49. data/spec/lib/ruby-lokalise-api/rest/comments_spec.rb +12 -0
  50. data/spec/lib/ruby-lokalise-api/rest/contributors_spec.rb +12 -0
  51. data/spec/lib/ruby-lokalise-api/rest/custom_translation_statuses_spec.rb +12 -0
  52. data/spec/lib/ruby-lokalise-api/rest/files_spec.rb +17 -9
  53. data/spec/lib/ruby-lokalise-api/rest/keys_spec.rb +12 -0
  54. data/spec/lib/ruby-lokalise-api/rest/orders_spec.rb +12 -0
  55. data/spec/lib/ruby-lokalise-api/rest/payment_cards_spec.rb +12 -0
  56. data/spec/lib/ruby-lokalise-api/rest/projects_spec.rb +12 -0
  57. data/spec/lib/ruby-lokalise-api/rest/queued_processes_spec.rb +58 -0
  58. data/spec/lib/ruby-lokalise-api/rest/screenshots_spec.rb +12 -0
  59. data/spec/lib/ruby-lokalise-api/rest/snapshots_spec.rb +25 -0
  60. data/spec/lib/ruby-lokalise-api/rest/tasks_spec.rb +12 -0
  61. data/spec/lib/ruby-lokalise-api/rest/team_users_spec.rb +12 -0
  62. data/spec/lib/ruby-lokalise-api/rest/translations_spec.rb +12 -0
  63. data/spec/lib/ruby-lokalise-api/rest/webhooks_spec.rb +13 -0
  64. metadata +11 -6
@@ -17,6 +17,7 @@ require 'ruby-lokalise-api/resources/base'
17
17
  require 'ruby-lokalise-api/resources/branch'
18
18
  require 'ruby-lokalise-api/resources/project'
19
19
  require 'ruby-lokalise-api/resources/project_language'
20
+ require 'ruby-lokalise-api/resources/queued_process'
20
21
  require 'ruby-lokalise-api/resources/key_comment'
21
22
  require 'ruby-lokalise-api/resources/contributor'
22
23
  require 'ruby-lokalise-api/resources/file'
@@ -43,6 +44,7 @@ require 'ruby-lokalise-api/collections/team'
43
44
  require 'ruby-lokalise-api/collections/system_language'
44
45
  require 'ruby-lokalise-api/collections/project_language'
45
46
  require 'ruby-lokalise-api/collections/project_comment'
47
+ require 'ruby-lokalise-api/collections/queued_process'
46
48
  require 'ruby-lokalise-api/collections/key_comment'
47
49
  require 'ruby-lokalise-api/collections/key'
48
50
  require 'ruby-lokalise-api/collections/contributor'
@@ -4,6 +4,7 @@ require 'ruby-lokalise-api/rest/branches'
4
4
  require 'ruby-lokalise-api/rest/languages'
5
5
  require 'ruby-lokalise-api/rest/teams'
6
6
  require 'ruby-lokalise-api/rest/projects'
7
+ require 'ruby-lokalise-api/rest/queued_processes'
7
8
  require 'ruby-lokalise-api/rest/comments'
8
9
  require 'ruby-lokalise-api/rest/keys'
9
10
  require 'ruby-lokalise-api/rest/contributors'
@@ -9,7 +9,7 @@ module Lokalise
9
9
  extend Lokalise::Utils::EndpointHelpers
10
10
 
11
11
  attr_reader :total_pages, :total_results, :results_per_page, :current_page, :collection,
12
- :project_id, :team_id, :request_params, :client, :path
12
+ :project_id, :team_id, :request_params, :client, :path, :branch
13
13
 
14
14
  # Initializes a new collection based on the response
15
15
  #
@@ -19,9 +19,10 @@ module Lokalise
19
19
  def initialize(response, params = {})
20
20
  produce_collection_for response
21
21
  populate_pagination_data_for response
22
- # Project and team id may not be present in some cases
22
+ # Project, team id and branch may not be present in some cases
23
23
  @project_id = response['content']['project_id']
24
24
  @team_id = response['content']['team_id']
25
+ @branch = response['content']['branch']
25
26
  @request_params = params
26
27
  @client = response['client']
27
28
  @path = response['path']
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lokalise
4
+ module Collections
5
+ class QueuedProcess < Base
6
+ DATA_KEY_PLURAL = 'Processes'
7
+
8
+ class << self
9
+ def endpoint(project_id, *_args)
10
+ path_from projects: [project_id, 'processes']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -105,6 +105,17 @@
105
105
  "settings",
106
106
  "statistics"
107
107
  ],
108
+ "queued_process": [
109
+ "process_id",
110
+ "type",
111
+ "status",
112
+ "message",
113
+ "created_by",
114
+ "created_by_email",
115
+ "created_at",
116
+ "created_at_timestamp",
117
+ "details"
118
+ ],
108
119
  "screenshot": [
109
120
  "screenshot_id",
110
121
  "key_ids",
@@ -211,4 +222,4 @@
211
222
  "events",
212
223
  "event_lang_map"
213
224
  ]
214
- }
225
+ }
@@ -8,25 +8,30 @@ module Lokalise
8
8
  include Lokalise::Utils::AttributeHelpers
9
9
  extend Lokalise::Utils::EndpointHelpers
10
10
 
11
- attr_reader :raw_data, :project_id, :client, :path
11
+ attr_reader :raw_data, :project_id, :client, :path, :branch
12
12
 
13
- # Initializes a new resource based on the response
13
+ # Initializes a new resource based on the response.
14
+ # `endpoint_generator` is used in cases when a new instance is generated
15
+ # from a different resource. For example, restoring from a snapshot
16
+ # creates a totally different project which should have a new path.
14
17
  #
15
18
  # @param response [Hash]
19
+ # @param endpoint_generator [Proc] Generate proper paths for certain resources
16
20
  # @return [Lokalise::Resources::Base]
17
- def initialize(response)
21
+ def initialize(response, endpoint_generator = nil)
18
22
  populate_attributes_for response['content']
19
23
 
20
24
  @raw_data = response['content']
21
25
  @project_id = response['content']['project_id']
26
+ @branch = response['content']['branch']
22
27
  @client = response['client']
23
- @path = infer_path_from response
28
+ @path = infer_path_from response, endpoint_generator
24
29
  end
25
30
 
26
31
  class << self
27
- # Dynamically add attribute readers for each inherited class.
32
+ # Dynamically adds attribute readers for each inherited class.
28
33
  # Attributes are defined in the `data/attributes.json` file.
29
- # Also set the `ATTRIBUTES` constant to assign values to each attribute later when
34
+ # Also sets the `ATTRIBUTES` constant to assign values to each attribute later when
30
35
  # the response arrives from the API
31
36
  def inherited(subclass)
32
37
  klass_attributes = attributes_for subclass
@@ -43,7 +48,8 @@ module Lokalise
43
48
  # Usage: `supports :update, :destroy, [:complex_method, '/sub/path', :update]`
44
49
  def supports(*methods)
45
50
  methods.each do |m_data|
46
- method_name, sub_path, c_method = m_data.is_a?(Array) ? m_data : [m_data, '', m_data]
51
+ method_name, sub_path, c_method =
52
+ m_data.is_a?(Array) ? m_data : [m_data, '', m_data]
47
53
  define_method method_name do |params = {}|
48
54
  path = instance_variable_get(:@path)
49
55
  # If there's a sub_path, preserve the initial path to allow further chaining
@@ -56,30 +62,34 @@ module Lokalise
56
62
 
57
63
  # Fetches a single record
58
64
  def find(client, path, params = {})
59
- new get(path, client, params)
65
+ new get(path, client, prepare_params(params))
60
66
  end
61
67
 
62
68
  # Creates one or multiple records
63
69
  def create(client, path, params)
64
- response = post path, client, params
65
-
70
+ response = post path, client, prepare_params(params)
66
71
  object_from response, params
67
72
  end
68
73
 
69
74
  # Updates one or multiple records
70
75
  def update(client, path, params)
71
- response = put path, client, params
72
-
76
+ response = put path, client, prepare_params(params)
73
77
  object_from response, params
74
78
  end
75
79
 
76
80
  # Destroys records by given ids
77
81
  def destroy(client, path, params = {})
78
- delete(path, client, params)['content']
82
+ delete(path, client, prepare_params(params))['content']
79
83
  end
80
84
 
81
85
  private
82
86
 
87
+ # Filters out internal attributes that should not be sent to Lokalise
88
+ def prepare_params(params)
89
+ filter_attrs = %i[_initial_path]
90
+ params.reject { |key, _v| filter_attrs.include?(key) }
91
+ end
92
+
83
93
  # Instantiates a new resource or collection based on the given response
84
94
  def object_from(response, params)
85
95
  model_class = name.base_class_name
@@ -96,7 +106,6 @@ module Lokalise
96
106
 
97
107
  def produce_resource(model_class, response)
98
108
  data_key_singular = data_key_for model_class
99
-
100
109
  if response['content'].key? data_key_singular
101
110
  data = response['content'].delete data_key_singular
102
111
  response['content'].merge! data
@@ -111,20 +120,27 @@ module Lokalise
111
120
  end
112
121
 
113
122
  # Generates path for the individual resource based on the path for the collection
114
- def infer_path_from(response)
123
+ def infer_path_from(response, endpoint_generator = nil)
115
124
  id_key = id_key_for self.class.name.base_class_name
116
125
  data_key = data_key_for self.class.name.base_class_name
117
126
 
118
- path_with_id response, id_key, data_key
127
+ path_with_id response, id_key, data_key, endpoint_generator
119
128
  end
120
129
 
121
- def path_with_id(response, id_key, data_key)
130
+ def path_with_id(response, id_key, data_key, endpoint_generator = nil)
122
131
  # Some resources do not have ids at all
123
132
  return nil unless response['content'].key?(id_key) || response['content'].key?(data_key)
124
133
 
125
134
  # ID of the resource
126
135
  id = id_from response, id_key, data_key
127
136
 
137
+ # If `endpoint_generator` is present, generate a new path
138
+ # based on the fetched id
139
+ if endpoint_generator
140
+ path = endpoint_generator.call project_id, id
141
+ return path.remove_trailing_slash
142
+ end
143
+
128
144
  path = response['path'] || response['base_path']
129
145
  # If path already has id - just return it
130
146
  return path if path.match?(/#{id}\z/)
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Branch < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def merge(params = {})
9
9
  self.class.merge @client, self.class.endpoint(project_id, branch_id, :merge), params
@@ -4,7 +4,7 @@ module Lokalise
4
4
  module Resources
5
5
  class Contributor < Base
6
6
  ID_KEY = 'user'
7
- supports :update, :destroy
7
+ supports :update, :destroy, [:reload_data, '', :find]
8
8
 
9
9
  class << self
10
10
  def endpoint(project_id, contributor_id = nil)
@@ -4,7 +4,7 @@ module Lokalise
4
4
  module Resources
5
5
  class CustomTranslationStatus < Base
6
6
  ID_KEY = 'status'
7
- supports :update, :destroy
7
+ supports :update, :destroy, [:reload_data, '', :find]
8
8
 
9
9
  class << self
10
10
  def colors(client, path, *_args)
@@ -9,7 +9,10 @@ module Lokalise
9
9
  end
10
10
 
11
11
  def upload(client, path, params)
12
- post(path, client, params)['content']
12
+ params[:queue] = true
13
+ klass = Lokalise::Resources::QueuedProcess
14
+ klass.new post(path, client, params),
15
+ ->(project_id, id) { klass.endpoint(project_id, id) }
13
16
  end
14
17
 
15
18
  def endpoint(project_id, action = '')
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Key < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  class << self
9
9
  def endpoint(project_id, key_id = nil)
@@ -5,7 +5,7 @@ module Lokalise
5
5
  class KeyComment < Base
6
6
  DATA_KEY = 'Comment'
7
7
  ID_KEY = 'comment'
8
- supports :destroy
8
+ supports :destroy, [:reload_data, '', :find]
9
9
 
10
10
  class << self
11
11
  def endpoint(project_id, key_id, comment_id = nil)
@@ -3,6 +3,8 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Order < Base
6
+ supports [:reload_data, '', :find]
7
+
6
8
  class << self
7
9
  def endpoint(team_id, order_id = nil)
8
10
  path_from teams: team_id,
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class PaymentCard < Base
6
- supports :destroy
6
+ supports :destroy, [:reload_data, '', :find]
7
7
 
8
8
  class << self
9
9
  def endpoint(card_id = nil)
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Project < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def empty
9
9
  self.class.empty @client, @path + '/empty'
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lokalise
4
+ module Resources
5
+ class QueuedProcess < Base
6
+ DATA_KEY = 'Process'
7
+ ID_KEY = 'process'
8
+ supports [:reload_data, '', :find]
9
+
10
+ class << self
11
+ def endpoint(project_id, process_id = nil)
12
+ path_from projects: project_id,
13
+ processes: process_id
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Screenshot < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  class << self
9
9
  def endpoint(project_id, screenshot_id = nil)
@@ -11,7 +11,9 @@ module Lokalise
11
11
 
12
12
  class << self
13
13
  def restore(client, path, *_args)
14
- Lokalise::Resources::Project.new post(path, client)
14
+ klass = Lokalise::Resources::Project
15
+ klass.new post(path, client),
16
+ ->(project_id, *_ids) { klass.endpoint(project_id) }
15
17
  end
16
18
 
17
19
  def endpoint(project_id, snapshot_id = nil)
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Task < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  class << self
9
9
  def endpoint(project_id, task_id = nil)
@@ -4,7 +4,7 @@ module Lokalise
4
4
  module Resources
5
5
  class TeamUser < Base
6
6
  ID_KEY = 'user'
7
- supports :update, :destroy
7
+ supports :update, :destroy, [:reload_data, '', :find]
8
8
 
9
9
  class << self
10
10
  def endpoint(team_id, team_user_id = nil)
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Translation < Base
6
- supports :update
6
+ supports :update, [:reload_data, '', :find]
7
7
 
8
8
  class << self
9
9
  def endpoint(project_id, translation_id = nil)
@@ -3,7 +3,7 @@
3
3
  module Lokalise
4
4
  module Resources
5
5
  class Webhook < Base
6
- supports :update, :destroy
6
+ supports :update, :destroy, [:reload_data, '', :find]
7
7
 
8
8
  def regenerate_secret
9
9
  self.class.regenerate_secret @client, @path + '/secret/regenerate'
@@ -4,7 +4,7 @@ module Lokalise
4
4
  class Client
5
5
  # Returns a single comment for the given key
6
6
  #
7
- # @see https://lokalise.co/api2docs/ruby/#transition-retrieve-a-comment-get
7
+ # @see https://app.lokalise.com/api2docs/curl/#transition-retrieve-a-comment-get
8
8
  # @return [Lokalise::Resources::Comment]
9
9
  # @param project_id [String]
10
10
  # @param key_id [String, Integer]
@@ -15,7 +15,7 @@ module Lokalise
15
15
 
16
16
  # Returns all comments for all keys inside the given project
17
17
  #
18
- # @see https://lokalise.co/api2docs/ruby/#transition-list-project-comments-get
18
+ # @see https://app.lokalise.com/api2docs/curl/#transition-list-project-comments-get
19
19
  # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
20
20
  # @param project_id [String]
21
21
  # @param params [Hash]
@@ -25,7 +25,7 @@ module Lokalise
25
25
 
26
26
  # Returns all comments for the given key inside the given project
27
27
  #
28
- # @see https://lokalise.co/api2docs/ruby/#transition-list-key-comments-get
28
+ # @see https://app.lokalise.com/api2docs/curl/#transition-list-key-comments-get
29
29
  # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
30
30
  # @param project_id [String]
31
31
  # @param key_id [String, Integer]
@@ -36,7 +36,7 @@ module Lokalise
36
36
 
37
37
  # Creates one or more comments for the given key inside the given project
38
38
  #
39
- # @see https://lokalise.co/api2docs/ruby/#transition-create-comments-post
39
+ # @see https://app.lokalise.com/api2docs/curl/#transition-create-comments-post
40
40
  # @return [Lokalise::Collection::Comment<Lokalise::Resources::Comment>]
41
41
  # @param project_id [String]
42
42
  # @param key_id [String, Integer]
@@ -47,7 +47,7 @@ module Lokalise
47
47
 
48
48
  # Deletes comment for the given key inside the given project
49
49
  #
50
- # @see https://lokalise.co/api2docs/ruby/#transition-delete-a-comment-delete
50
+ # @see https://app.lokalise.com/api2docs/curl/#transition-delete-a-comment-delete
51
51
  # @return [Hash]
52
52
  # @param project_id [String]
53
53
  # @param key_id [String, Integer]
@@ -4,7 +4,7 @@ module Lokalise
4
4
  class Client
5
5
  # Returns all contributors for the given project
6
6
  #
7
- # @see https://lokalise.co/api2docs/ruby/#transition-list-all-contributors-get
7
+ # @see https://app.lokalise.com/api2docs/curl/#transition-list-all-contributors-get
8
8
  # @return [Lokalise::Collection::Contributor<Lokalise::Resources::Contributor>]
9
9
  # @param project_id [String]
10
10
  # @param params [Hash]
@@ -14,7 +14,7 @@ module Lokalise
14
14
 
15
15
  # Returns a single contributor for the given project
16
16
  #
17
- # @see https://lokalise.co/api2docs/ruby/#transition-retrieve-a-contributor-get
17
+ # @see https://app.lokalise.com/api2docs/curl/#transition-retrieve-a-contributor-get
18
18
  # @return [Lokalise::Resources::Contributor]
19
19
  # @param project_id [String]
20
20
  # @param contributor_id [String, Integer]
@@ -24,7 +24,7 @@ module Lokalise
24
24
 
25
25
  # Creates one or more contributors inside the given project
26
26
  #
27
- # @see https://lokalise.co/api2docs/ruby/#transition-create-contributors-post
27
+ # @see https://app.lokalise.com/api2docs/curl/#transition-create-contributors-post
28
28
  # @return [Lokalise::Collection::Contributor<Lokalise::Resources::Contributor>]
29
29
  # @param project_id [String]
30
30
  # @param params [Hash, Array<Hash>]
@@ -34,7 +34,7 @@ module Lokalise
34
34
 
35
35
  # Updates the given contributor inside the given project
36
36
  #
37
- # @see https://lokalise.co/api2docs/ruby/#transition-update-a-contributor-put
37
+ # @see https://app.lokalise.com/api2docs/curl/#transition-update-a-contributor-put
38
38
  # @return [Lokalise::Resources::Contributor]
39
39
  # @param project_id [String]
40
40
  # @param contributor_id [String, Integer]
@@ -45,7 +45,7 @@ module Lokalise
45
45
 
46
46
  # Deletes contributor inside the given project
47
47
  #
48
- # @see https://lokalise.co/api2docs/ruby/#transition-delete-a-contributor-delete
48
+ # @see https://app.lokalise.com/api2docs/curl/#transition-delete-a-contributor-delete
49
49
  # @return [Hash]
50
50
  # @param project_id [String]
51
51
  # @param contributor_id [String, Integer]