ruby-lokalise-api 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -2
  3. data/README.md +172 -10
  4. data/lib/ruby-lokalise-api.rb +2 -0
  5. data/lib/ruby-lokalise-api/client.rb +18 -0
  6. data/lib/ruby-lokalise-api/collections/base.rb +11 -10
  7. data/lib/ruby-lokalise-api/collections/contributor.rb +1 -3
  8. data/lib/ruby-lokalise-api/collections/file.rb +1 -3
  9. data/lib/ruby-lokalise-api/collections/key.rb +8 -3
  10. data/lib/ruby-lokalise-api/collections/key_comment.rb +2 -3
  11. data/lib/ruby-lokalise-api/collections/project.rb +1 -3
  12. data/lib/ruby-lokalise-api/collections/project_comment.rb +1 -3
  13. data/lib/ruby-lokalise-api/collections/project_language.rb +1 -3
  14. data/lib/ruby-lokalise-api/collections/screenshot.rb +1 -3
  15. data/lib/ruby-lokalise-api/collections/snapshot.rb +1 -3
  16. data/lib/ruby-lokalise-api/collections/system_language.rb +1 -3
  17. data/lib/ruby-lokalise-api/collections/task.rb +1 -3
  18. data/lib/ruby-lokalise-api/collections/team.rb +1 -3
  19. data/lib/ruby-lokalise-api/collections/team_user.rb +1 -3
  20. data/lib/ruby-lokalise-api/collections/translation.rb +1 -3
  21. data/lib/ruby-lokalise-api/error.rb +2 -0
  22. data/lib/ruby-lokalise-api/request.rb +11 -3
  23. data/lib/ruby-lokalise-api/resources/base.rb +51 -41
  24. data/lib/ruby-lokalise-api/resources/contributor.rb +6 -4
  25. data/lib/ruby-lokalise-api/resources/file.rb +7 -12
  26. data/lib/ruby-lokalise-api/resources/key.rb +5 -4
  27. data/lib/ruby-lokalise-api/resources/key_comment.rb +6 -4
  28. data/lib/ruby-lokalise-api/resources/project.rb +10 -7
  29. data/lib/ruby-lokalise-api/resources/project_language.rb +5 -4
  30. data/lib/ruby-lokalise-api/resources/screenshot.rb +5 -4
  31. data/lib/ruby-lokalise-api/resources/snapshot.rb +10 -5
  32. data/lib/ruby-lokalise-api/resources/task.rb +5 -4
  33. data/lib/ruby-lokalise-api/resources/team_user.rb +6 -4
  34. data/lib/ruby-lokalise-api/resources/translation.rb +5 -4
  35. data/lib/ruby-lokalise-api/rest/comments.rb +6 -6
  36. data/lib/ruby-lokalise-api/rest/contributors.rb +6 -6
  37. data/lib/ruby-lokalise-api/rest/files.rb +3 -3
  38. data/lib/ruby-lokalise-api/rest/keys.rb +9 -9
  39. data/lib/ruby-lokalise-api/rest/languages.rb +7 -7
  40. data/lib/ruby-lokalise-api/rest/projects.rb +7 -7
  41. data/lib/ruby-lokalise-api/rest/screenshots.rb +6 -6
  42. data/lib/ruby-lokalise-api/rest/snapshots.rb +5 -5
  43. data/lib/ruby-lokalise-api/rest/tasks.rb +6 -6
  44. data/lib/ruby-lokalise-api/rest/team_users.rb +5 -5
  45. data/lib/ruby-lokalise-api/rest/teams.rb +1 -1
  46. data/lib/ruby-lokalise-api/rest/translations.rb +3 -3
  47. data/lib/ruby-lokalise-api/utils/attribute_helpers.rb +19 -5
  48. data/lib/ruby-lokalise-api/utils/endpoint_helpers.rb +12 -0
  49. data/lib/ruby-lokalise-api/utils/string_utils.rb +4 -0
  50. data/lib/ruby-lokalise-api/version.rb +1 -1
  51. data/ruby-lokalise-api.gemspec +1 -0
  52. data/spec/lib/ruby-lokalise-api/rest/comments_spec.rb +22 -5
  53. data/spec/lib/ruby-lokalise-api/rest/contributors_spec.rb +35 -2
  54. data/spec/lib/ruby-lokalise-api/rest/keys_spec.rb +55 -4
  55. data/spec/lib/ruby-lokalise-api/rest/languages_spec.rb +31 -2
  56. data/spec/lib/ruby-lokalise-api/rest/projects_spec.rb +36 -2
  57. data/spec/lib/ruby-lokalise-api/rest/screenshots_spec.rb +45 -8
  58. data/spec/lib/ruby-lokalise-api/rest/snapshots_spec.rb +25 -2
  59. data/spec/lib/ruby-lokalise-api/rest/tasks_spec.rb +38 -2
  60. data/spec/lib/ruby-lokalise-api/rest/team_users_spec.rb +25 -2
  61. data/spec/lib/ruby-lokalise-api/rest/translations_spec.rb +17 -3
  62. metadata +17 -2
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Contributor < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/contributors"
6
+ path_from projects: [project_id, 'contributors']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class File < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/files"
6
+ path_from projects: [project_id, 'files']
9
7
  end
10
8
  end
11
9
  end
@@ -1,11 +1,16 @@
1
1
  module Lokalise
2
2
  module Collections
3
3
  class Key < Base
4
- class << self
5
- private
4
+ # Destroys all keys in the collection
5
+ # @return [Hash]
6
+ def destroy_all
7
+ keys = collection.collect(&:key_id)
8
+ Lokalise::Resources::Key.destroy @client, @path, keys: keys
9
+ end
6
10
 
11
+ class << self
7
12
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/keys"
13
+ path_from projects: [project_id, 'keys']
9
14
  end
10
15
  end
11
16
  end
@@ -2,10 +2,9 @@ module Lokalise
2
2
  module Collections
3
3
  class KeyComment < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, key_id, *_args)
8
- "projects/#{project_id}/keys/#{key_id}/comments"
6
+ path_from projects: project_id,
7
+ keys: [key_id, 'comments']
9
8
  end
10
9
  end
11
10
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Project < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(*_args)
8
- 'projects'
6
+ path_from projects: nil
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class ProjectComment < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/comments"
6
+ path_from projects: [project_id, 'comments']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class ProjectLanguage < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/languages"
6
+ path_from projects: [project_id, 'languages']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Screenshot < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/screenshots"
6
+ path_from projects: [project_id, 'screenshots']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Snapshot < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/snapshots"
6
+ path_from projects: [project_id, 'snapshots']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class SystemLanguage < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(*_args)
8
- 'system/languages'
6
+ path_from system: 'languages'
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Task < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/tasks"
6
+ path_from projects: [project_id, 'tasks']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Team < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(*_args)
8
- 'teams'
6
+ path_from teams: nil
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class TeamUser < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(team_id, *_args)
8
- "teams/#{team_id}/users"
6
+ path_from teams: [team_id, 'users']
9
7
  end
10
8
  end
11
9
  end
@@ -2,10 +2,8 @@ module Lokalise
2
2
  module Collections
3
3
  class Translation < Base
4
4
  class << self
5
- private
6
-
7
5
  def endpoint(project_id, *_args)
8
- "projects/#{project_id}/translations"
6
+ path_from projects: [project_id, 'translations']
9
7
  end
10
8
  end
11
9
  end
@@ -11,6 +11,7 @@ module Lokalise
11
11
  TooManyRequests = Class.new(ClientError)
12
12
  Forbidden = Class.new(ClientError)
13
13
  Locked = Class.new(ClientError)
14
+ MethodNowAllowed = Class.new(ClientError)
14
15
 
15
16
  NotImplemented = Class.new(ServerError)
16
17
  BadGateway = Class.new(ServerError)
@@ -22,6 +23,7 @@ module Lokalise
22
23
  401 => Lokalise::Error::Unauthorized,
23
24
  403 => Lokalise::Error::Forbidden,
24
25
  404 => Lokalise::Error::NotFound,
26
+ 405 => Lokalise::Error::MethodNowAllowed,
25
27
  406 => Lokalise::Error::NotAcceptable,
26
28
  409 => Lokalise::Error::Conflict,
27
29
  423 => Lokalise::Error::Locked,
@@ -38,18 +38,26 @@ module Lokalise
38
38
 
39
39
  private
40
40
 
41
+ # Get rid of double slashes in the `path` and leading slash
41
42
  def prepare(path)
42
- path.gsub %r{//}, '/'
43
+ path.gsub(%r{\A/}, '').gsub %r{//}, '/'
43
44
  end
44
45
 
45
46
  def respond_with(response, client)
46
47
  body = MultiJson.load response.body
48
+ uri = Addressable::URI.parse response.env.url
47
49
  respond_with_error(response.status, body) if body.respond_to?(:has_key?) && body.key?('error')
50
+ extract_headers_from(response).
51
+ merge('content' => body,
52
+ 'client' => client,
53
+ 'path' => uri.path.gsub(%r{/api2/}, ''))
54
+ end
55
+
56
+ def extract_headers_from(response)
48
57
  response.
49
58
  headers.
50
59
  to_h.
51
- keep_if { |k, _v| PAGINATION_HEADERS.include?(k) }.
52
- merge('content' => body, 'client' => client)
60
+ keep_if { |k, _v| PAGINATION_HEADERS.include?(k) }
53
61
  end
54
62
 
55
63
  def respond_with_error(code, body)
@@ -4,8 +4,9 @@ module Lokalise
4
4
  extend Lokalise::Request
5
5
  extend Lokalise::Utils::AttributeHelpers
6
6
  include Lokalise::Utils::AttributeHelpers
7
+ extend Lokalise::Utils::EndpointHelpers
7
8
 
8
- attr_reader :raw_data, :project_id, :client
9
+ attr_reader :raw_data, :project_id, :client, :path
9
10
 
10
11
  # Initializes a new resource based on the response
11
12
  #
@@ -17,6 +18,7 @@ module Lokalise
17
18
  @raw_data = response['content']
18
19
  @project_id = response['content']['project_id']
19
20
  @client = response['client']
21
+ @path = infer_path_from response
20
22
  end
21
23
 
22
24
  class << self
@@ -33,68 +35,53 @@ module Lokalise
33
35
  super
34
36
  end
35
37
 
38
+ # Defines common CRUD instance methods
39
+ # Usage: `supports :update, :destroy`
40
+ def supports(*methods)
41
+ methods.each do |method_name|
42
+ define_method method_name do |params = {}|
43
+ self.class.send method_name,
44
+ instance_variable_get(:@client),
45
+ instance_variable_get(:@path),
46
+ params
47
+ end
48
+ end
49
+ end
50
+
36
51
  # Fetches a single record
37
- def find(client, endpoint_ids, resource_id = '', params = {})
38
- new get("#{endpoint(*endpoint_ids)}/#{resource_id}",
39
- client,
40
- params)
52
+ def find(client, path, params = {})
53
+ new get(path, client, params)
41
54
  end
42
55
 
43
56
  # Creates one or multiple records
44
- def create(client, endpoint_ids, params, object_key = nil)
45
- response = post(endpoint(*endpoint_ids),
46
- client,
47
- body_from(params, object_key))
57
+ def create(client, path, params)
58
+ response = post path, client, params
48
59
 
49
- object_from response, params, endpoint_ids
60
+ object_from response, params
50
61
  end
51
62
 
52
63
  # Updates one or multiple records
53
- def update(client, endpoint_ids, resource_id, params, object_key = nil)
54
- response = put("#{endpoint(*endpoint_ids)}/#{resource_id}",
55
- client,
56
- body_from(params, object_key))
64
+ def update(client, path, params)
65
+ response = put path, client, params
57
66
 
58
- object_from response, params, endpoint_ids
67
+ object_from response, params
59
68
  end
60
69
 
61
70
  # Destroys records by given ids
62
- #
63
- # @param client [Lokalise::Client]
64
- # @return [Hash]
65
- # @param endpoint_ids [String, Integer, Array]
66
- # @param resource_id [String, Integer, Hash<Array>]
67
- def destroy(client, endpoint_ids, resource_id)
68
- path = endpoint(*endpoint_ids).to_s
69
- if resource_id.is_a?(Hash)
70
- delete path, client, resource_id
71
- else
72
- delete "#{path}/#{resource_id}", client
73
- end['content']
71
+ def destroy(client, path, params = {})
72
+ delete(path, client, params)['content']
74
73
  end
75
74
 
76
75
  private
77
76
 
78
- # Converts `params` to hash with arrays under the `object_key` key.
79
- # Used in bulk operations
80
- #
81
- # @return [Hash]
82
- def body_from(params, object_key)
83
- return params unless object_key
84
-
85
- params = [params] unless params.is_a?(Array)
86
- Hash[object_key, params]
87
- end
88
-
89
77
  # Instantiates a new resource or collection based on the given response
90
- def object_from(response, params, endpoint_ids)
78
+ def object_from(response, params)
91
79
  model_class = name.base_class_name
92
80
  data_key_plural = data_key_for model_class, true
93
81
 
94
82
  if response['content'].key? data_key_plural
95
83
  Module.const_get("Lokalise::Collections::#{model_class}").new response,
96
- params,
97
- endpoint_ids
84
+ params
98
85
  else
99
86
  new response
100
87
  end
@@ -103,6 +90,29 @@ module Lokalise
103
90
 
104
91
  private
105
92
 
93
+ # Generates path for the individual resource based on the path for the collection
94
+ def infer_path_from(response)
95
+ id_key = id_key_for self.class.name.base_class_name
96
+ data_key = data_key_for self.class.name.base_class_name
97
+
98
+ path_with_id response, id_key, data_key
99
+ end
100
+
101
+ def path_with_id(response, id_key, data_key)
102
+ # Some resources do not have ids at all
103
+ return nil unless response['content'].key?(id_key) || response['content'].key?(data_key)
104
+
105
+ # Content may be `{"project_id": '123', ...}` or {"snapshot": {"snapshot_id": '123', ...}}
106
+ id = response['content'][id_key] || response['content'][data_key][id_key]
107
+
108
+ path = response['path'] || response['base_path']
109
+ # If path already has id - just return it
110
+ return path if path.match?(/#{id}\z/)
111
+
112
+ # Otherwise this seems like a collection path, so append the resource id to it
113
+ path.remove_trailing_slash + "/#{id}"
114
+ end
115
+
106
116
  # Store all resources attributes under the corresponding instance variables.
107
117
  # `ATTRIBUTES` is defined inside resource-specific classes
108
118
  def populate_attributes_for(content)
@@ -1,11 +1,13 @@
1
1
  module Lokalise
2
2
  module Resources
3
3
  class Contributor < Base
4
- class << self
5
- private
4
+ ID_KEY = 'user'.freeze
5
+ supports :update, :destroy
6
6
 
7
- def endpoint(project_id)
8
- "projects/#{project_id}/contributors"
7
+ class << self
8
+ def endpoint(project_id, contributor_id = nil)
9
+ path_from projects: project_id,
10
+ contributors: contributor_id
9
11
  end
10
12
  end
11
13
  end
@@ -2,22 +2,17 @@ module Lokalise
2
2
  module Resources
3
3
  class File < Base
4
4
  class << self
5
- def download(client, project_id, params)
6
- up_down client, endpoint(project_id), params, 'download'
5
+ def download(client, path, params)
6
+ post(path, client, params)['content']
7
7
  end
8
8
 
9
- def upload(client, project_id, params)
10
- up_down client, endpoint(project_id), params, 'upload'
9
+ def upload(client, path, params)
10
+ post(path, client, params)['content']
11
11
  end
12
12
 
13
- private
14
-
15
- def up_down(client, path, params, action)
16
- post("#{path}/#{action}", client, params)['content']
17
- end
18
-
19
- def endpoint(project_id)
20
- "projects/#{project_id}/files"
13
+ def endpoint(project_id, action = '')
14
+ path_from projects: project_id,
15
+ files: action
21
16
  end
22
17
  end
23
18
  end
@@ -1,11 +1,12 @@
1
1
  module Lokalise
2
2
  module Resources
3
3
  class Key < Base
4
- class << self
5
- private
4
+ supports :update, :destroy
6
5
 
7
- def endpoint(project_id)
8
- "projects/#{project_id}/keys"
6
+ class << self
7
+ def endpoint(project_id, key_id = nil)
8
+ path_from projects: project_id,
9
+ keys: key_id
9
10
  end
10
11
  end
11
12
  end