mini_api 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d964fdc02d20eb94726fd7ce97316402f97369aa0639f6ae8f4c4761d1359ed4
4
- data.tar.gz: 76c2ac644e655cec1b23199c843c56008b23730e671d40499dac66c305f34f6f
3
+ metadata.gz: 3fbf83309b4f2fccd1e62e7e53cb0bf955472f68f1aa0a5a57517976c478fc97
4
+ data.tar.gz: 343a0d838eeb146e2c35dd7a483872825b330caa0afd54267ed34e9fe164f13a
5
5
  SHA512:
6
- metadata.gz: a84f16e06ce682471041e1a6c03cc9d991f482db377854cd0c6a533b570867654bf77cea9e7074a8a5ee2f7f219ae3fb22d192dc8ad3d8ac4bdc0b4b0cc57fe2
7
- data.tar.gz: 85d339e62fa8195be1d02289e6fb00759b1a401cc428029a2cae6deb39403d24cf34f487bc21f493eed3d67c8f904f1ffbeb139f8191946490c7065ae53821f7
6
+ metadata.gz: 76fa5b3615b1a7dee108f5c236356398cde720a9f281314c3dca45616eaf4cc1d7c0baf5a02b991219bfb7d49c7937f43a2a29514749d064ec4b4ad33d55aa92
7
+ data.tar.gz: ee55e68cde7652108534bd1d62c9462303b64e92b62be836b240cacb4cb1354983e7818d46dbe25da61ea7c69f638201b27c393498a076609433e94c069e44ff
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ![](https://github.com/leoncruz/api-responder/actions/workflows/tests.yml/badge.svg)
2
- [![Maintainability](https://api.codeclimate.com/v1/badges/ec2939be693459b7ce4d/maintainability)](https://codeclimate.com/github/leoncruz/api-responder/maintainability)
3
- [![Test Coverage](https://api.codeclimate.com/v1/badges/ec2939be693459b7ce4d/test_coverage)](https://codeclimate.com/github/leoncruz/api-responder/test_coverage)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/6ed70a7ed0d28e32b56c/maintainability)](https://codeclimate.com/github/leoncruz/mini_api/maintainability)
3
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/6ed70a7ed0d28e32b56c/test_coverage)](https://codeclimate.com/github/leoncruz/mini_api/test_coverage)
4
4
 
5
5
  # Mini Api
6
6
  A gem to standardize json responses in Rails applications, highly inspired on [Responders](https://github.com/heartcombo/responders)
@@ -8,7 +8,10 @@ A gem to standardize json responses in Rails applications, highly inspired on [R
8
8
  ## Table of Contents
9
9
  - [Usage](#usage)
10
10
  - [Respondering json](#respondering-json)
11
+ - [Data Serialization](#data-serialization)
11
12
  - [Success and failure actions](#success-and-failure-actions)
13
+ - [Errors](#errors)
14
+ - [Message](#message)
12
15
  - [Transform keys](#transform-keys)
13
16
  - [Overriding response](#overriding-response)
14
17
  - [Pagination](#pagination)
@@ -28,7 +31,6 @@ $ bundle
28
31
  ```
29
32
 
30
33
  You must install [Kaminari](https://github.com/kaminari/kaminari) to handle pagination
31
- and [Active Model Serializers](http://github.com/rails-api/active_model_serializers) to handle data serialization
32
34
 
33
35
  ## Usage
34
36
 
@@ -90,6 +92,22 @@ The response will be like:
90
92
  }
91
93
  ```
92
94
 
95
+ ### Data Serialization
96
+
97
+ This gem is integrated to [Alba](https://github.com/okuramasafumi/Alba) to create your `resources`. A simple resource example:
98
+ ```ruby
99
+ class UserResource
100
+ include Alba::Resource
101
+
102
+ attributes :id, :name, :email
103
+ end
104
+ ```
105
+ When the `render_json` methods receive an instance of `user` or a `ActiveRecord::Relation` of `users` will search by `UserResource`.
106
+
107
+ If you have a nested controller like: `Api::V1::UsersController`, `mini_api` will search by resources in controller namespace.
108
+ First will search per `Api::V1::UserResource`, after `Api::UserResource` and then `UserResource` until find.
109
+ That way, even if your `controller` and `resource` are defined in different namespace levels, `MiniApi` will find.
110
+
93
111
  ### Success and failure actions
94
112
 
95
113
  Many times, our controller actions need to persist or validate some data coming from request, the default approach to do that is like:
@@ -142,6 +160,50 @@ The `message` key is different based on actions on informed model: create, updat
142
160
 
143
161
  You can respond any type of data, but ActiveRecord/ActiveModel::Model and ActiveRecord::Relation has a special treatment as shown above
144
162
 
163
+ ### Errors
164
+ To show errors of a model, by default will use the `errors.messages` method, but `MiniApi` adds an ability to `Alba` to create a error resource
165
+ as a nested class in your resource. Example:
166
+
167
+ ```ruby
168
+ class UserResource
169
+ include Alba::Resource
170
+
171
+ attributes :id, :name, :email
172
+
173
+ class Error
174
+ include Alba::Resource
175
+
176
+ attribute :user do
177
+ object.errors.full_messages
178
+ end
179
+ end
180
+ end
181
+ ```
182
+ The response will be like:
183
+ ```json
184
+ {
185
+ "success": false,
186
+ "errors": {
187
+ "user": ["First name can't be blank"]
188
+ },
189
+ "message": "User could not be created."
190
+ }
191
+ ```
192
+ You can create serializers for non `ActiveRecord` and add a nested `Error` class too
193
+
194
+ ### Message
195
+
196
+ The `I18n` path for the key `message` is `mini_api.messages.actions`, the controller action name and the `notice` for success actions
197
+ or `alert` for failure actions. Example `mini_api.messages.actions.create.notice`
198
+
199
+ By default support the actions: `create`, `update` and `delete`, but you can add more actions to translate
200
+
201
+ You can add translation based on models, changing the `action` key for your model name. Example:
202
+ `mini_api.messages.model_name.create.alert`. With this, is more easy personalize messages
203
+
204
+ It is possible define a translation based on controller, useful if you use nested controlers. The path is:
205
+ `min_api.messages.controller_name.action_name.alert`
206
+
145
207
  ### Transform keys
146
208
 
147
209
  It is possible to transform the keys of request and response. By default, will transform to `snake_case`, but the possible values are `snake_case`, `camel_lower` and `camel_case`
@@ -15,11 +15,18 @@ module MiniApi
15
15
 
16
16
  data = transform_keys
17
17
 
18
+ body =
19
+ if success
20
+ { data: data }
21
+ else
22
+ { errors: data }
23
+ end
24
+
18
25
  @controller.render(
19
26
  json: {
20
27
  success: success,
21
- data: data,
22
- message: @options[:message] || nil
28
+ message: @options[:message] || nil,
29
+ **body
23
30
  },
24
31
  status: @options[:status] || :ok
25
32
  )
@@ -2,11 +2,13 @@
2
2
 
3
3
  require 'mini_api/serialization'
4
4
  require 'mini_api/case_transform'
5
+ require 'mini_api/translation/message'
5
6
 
6
7
  module MiniApi
7
8
  # class to handle json render of ActiveRecord::Base instances and ActiveModel::Model's
8
9
  class ModelResponder
9
10
  include Serialization
11
+ include Translation::Message
10
12
 
11
13
  def initialize(controller, resource, options = {})
12
14
  @controller = controller
@@ -17,20 +19,16 @@ module MiniApi
17
19
  def respond
18
20
  body = {
19
21
  success: resource_has_errors? == false,
20
- message: @options[:message] || default_message
22
+ message: @options[:message] || message
21
23
  }
22
24
 
23
25
  body =
24
26
  if resource_has_errors?
25
- { errors: @resource.errors.messages }.merge(body)
27
+ errors.merge(body)
26
28
  else
27
29
  { data: serialiable_body(@resource).as_json }.merge(body)
28
30
  end
29
31
 
30
- # This is for an problem with ActiveModelSerializer that adds an error
31
- # attribute when resource is an ActiveModel instance
32
- body[:data] = body[:data].except('errors') if body[:data]&.key?('errors')
33
-
34
32
  body = CaseTransform.response_keys(body)
35
33
 
36
34
  @controller.render json: body, status: status_code
@@ -42,6 +40,14 @@ module MiniApi
42
40
  !@resource.errors.empty?
43
41
  end
44
42
 
43
+ def errors
44
+ error_serializer = get_error_serializer(@resource)
45
+
46
+ return { errors: @resource.errors.messages } unless error_serializer
47
+
48
+ { errors: error_serializer.new(@resource).as_json }
49
+ end
50
+
45
51
  def status_code
46
52
  return @options[:status] if @options[:status].present?
47
53
 
@@ -54,17 +60,6 @@ module MiniApi
54
60
  :ok
55
61
  end
56
62
 
57
- def default_message
58
- kind = resource_has_errors? ? 'alert' : 'notice'
59
-
60
- I18n.t(
61
- kind,
62
- scope: [:mini_api, :messages, :actions, @controller.action_name],
63
- resource_name: @resource.class.model_name.human,
64
- default: ''
65
- )
66
- end
67
-
68
63
  def previously_new_record?
69
64
  return true if @resource.is_a?(ActiveRecord::Base) && @resource.previously_new_record?
70
65
 
@@ -1,16 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module MiniApi
4
- #
5
- # This module is responsible to handler integration with Active Model Serialier gem
6
- # call the +get_serializer+ method of controller implemented by gem
7
- # to find the serializer of informed object.
3
+ require 'alba'
8
4
 
5
+ module MiniApi
9
6
  module Serialization
7
+ # This method search by serializer using the module parents of controller.
8
+ # With this, is possible define serializers for the same resource
9
+ # in different controller scopes
10
10
  def serialiable_body(resource)
11
- return resource unless defined?(ActiveModel::Serializer)
11
+ controller_scope = @controller.class.module_parents
12
+
13
+ resource_class =
14
+ if resource.respond_to?(:model)
15
+ resource.model
16
+ else
17
+ resource.class
18
+ end
19
+
20
+ serializer_class =
21
+ loop do
22
+ serializer_class =
23
+ "#{controller_scope.first}::#{resource_class}Resource".safe_constantize
24
+
25
+ break serializer_class if serializer_class
26
+
27
+ break DefaultResource if controller_scope.empty?
28
+
29
+ controller_scope.shift
30
+ end
31
+
32
+ serializer_class.new(resource)
33
+ end
34
+
35
+ # Search by the nested class +Error+ on serializer
36
+ # Follow the same steps for +get_serializer+
37
+ def get_error_serializer(resource)
38
+ error_serializer = serialiable_body(resource)
39
+
40
+ return unless error_serializer
41
+
42
+ "#{error_serializer.class}::Error".safe_constantize
43
+ end
12
44
 
13
- @controller.get_serializer(resource)
45
+ # Empty serializer class for when resource does not have a custom class
46
+ class DefaultResource
47
+ include Alba::Resource
14
48
  end
15
49
  end
16
50
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniApi
4
+ module Translation
5
+ # Module to handle the +message+ key on json response.
6
+ # Will identify if model has errors or not and define the I18n path to +notice+, for model without errors
7
+ # and +alert+ for model with errors.
8
+ # There is three possible path for messages:
9
+ #
10
+ # The path based on model name
11
+ # mini_api:
12
+ # messages:
13
+ # model_name:
14
+ # action_name:
15
+ # notitce:
16
+ # alert:
17
+ #
18
+ # The path based on controller name
19
+ # mini_api:
20
+ # messages:
21
+ # controller:
22
+ # controller_name:
23
+ # action_name:
24
+ # notitce:
25
+ # alert:
26
+ #
27
+ # And the last, is per action path:
28
+ # mini_api:
29
+ # messages:
30
+ # actions:
31
+ # create:
32
+ # notice: '%{resource_name} foi criado com sucesso.'
33
+ # alert: '%{resource_name} não pôde ser criado.'
34
+
35
+ module Message
36
+ def message
37
+ kind = @resource.errors.empty? ? 'notice' : 'alert'
38
+
39
+ I18n.t(
40
+ kind,
41
+ scope: model_message_path || controller_message_path || default_message_path,
42
+ resource_name: @resource.class.model_name.human,
43
+ default: ''
44
+ )
45
+ end
46
+
47
+ private
48
+
49
+ def model_message_path
50
+ model_path = "mini_api.messages.#{@resource.model_name.i18n_key}.#{@controller.action_name}"
51
+
52
+ model_path if I18n.exists? model_path
53
+ end
54
+
55
+ def controller_message_path
56
+ controller_path =
57
+ "mini_api.messages.controller.#{@controller.controller_name}.#{@controller.action_name}"
58
+
59
+ controller_path if I18n.exists? controller_path
60
+ end
61
+
62
+ def default_message_path
63
+ ['mini_api', 'messages', 'actions', @controller.action_name].join('.')
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniApi
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.5'
5
5
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leon Cruz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-19 00:00:00.000000000 Z
11
+ date: 2023-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: alba
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rails
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -46,6 +60,7 @@ files:
46
60
  - lib/mini_api/relation_responder.rb
47
61
  - lib/mini_api/responder.rb
48
62
  - lib/mini_api/serialization.rb
63
+ - lib/mini_api/translation/message.rb
49
64
  - lib/mini_api/version.rb
50
65
  homepage:
51
66
  licenses: