mini_api 0.1.2 → 0.1.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6068dbc415de617d267b2e42d438eb85f36fdbbf0d083cf63efe86042130f96
4
- data.tar.gz: 31f694de691b4c4d271d0d38273a5df7476aa6bb2118ecceadeca639ca7883f9
3
+ metadata.gz: bf126960ba6eec18c20dcf69715848c827eef16840540c45fe0d76fc1a61341c
4
+ data.tar.gz: 69caf5e66fdacee7e9b5a4c5271387e0823f6f10f90373b9cdd149966563ad3f
5
5
  SHA512:
6
- metadata.gz: 287a2711d205b18d07fb6295e36bf132ef64953aa6d91a2f2f8699fdecaf82cc5fe0cd3a2292235f523ecf36ce6983c40b6d99a3a5d89418fe295ef4c834275c
7
- data.tar.gz: 8045d230ca7765a976b34ec73b5fe9020bdf7b40f662de12a1e1b5a0e72cd2c446c3d859f91e0921467c179eb6a6b0aa2fdc2af39dc3ba169586937775934d2f
6
+ metadata.gz: 11a71582b7e0ed144cc0d3256dabc4c2e7f2f459c81459f2d809af16ddd02de0ee9ec9af45cdc6fbaae4d2c809857148b668e47186c0c110a1b708153f687373
7
+ data.tar.gz: c34d2b7773016ccd2328778d1d8b9a9be5cca14c403684b3870dfe47d3fe5988ae3acad1ec0bcb2453468304b4a329e16a35aa7f72efec48f64d9da1ca2fcf19
data/README.md CHANGED
@@ -9,6 +9,9 @@ A gem to standardize json responses in Rails applications, highly inspired on [R
9
9
  - [Usage](#usage)
10
10
  - [Respondering json](#respondering-json)
11
11
  - [Success and failure actions](#success-and-failure-actions)
12
+ - [Errors](#errors)
13
+ - [Message](#message)
14
+ - [Transform keys](#transform-keys)
12
15
  - [Overriding response](#overriding-response)
13
16
  - [Pagination](#pagination)
14
17
  - [Contributing](#contributing)
@@ -141,6 +144,64 @@ The `message` key is different based on actions on informed model: create, updat
141
144
 
142
145
  You can respond any type of data, but ActiveRecord/ActiveModel::Model and ActiveRecord::Relation has a special treatment as shown above
143
146
 
147
+ ### Errors
148
+ To show errors of a model, by default will use the `errors.messages` method, but `MiniApi` adds an ability to `active_model_serializers` to create a error serializer
149
+ as a nested class in your serializer. Example:
150
+ ```ruby
151
+ class UserSerializer < ActiveModel::Serializer
152
+ attributes :id, :first_name, :last_name
153
+
154
+ class Error < ActiveModel::Serializer
155
+ attributes :user
156
+
157
+ def user
158
+ {
159
+ first_name: object.errors[:first_name],
160
+ last_name: object.errors[:last_name],
161
+ }
162
+ end
163
+ end
164
+ end
165
+ ```
166
+ The response will be like:
167
+ ```json
168
+ {
169
+ "success": false,
170
+ "errors": {
171
+ "user": {
172
+ "first_name": "can't be blank",
173
+ "last_name": "can't be blank"
174
+ }
175
+ },
176
+ "message": "User could not be created."
177
+ }
178
+ ```
179
+ You can create serializers for non `ActiveRecord` and add a nested `Error` class too
180
+
181
+ ### Message
182
+
183
+ The `I18n` path for the key `message` is `mini_api.messages.actions`, the controller action name and the `notice` for success actions
184
+ or `alert` for failure actions. Example `mini_api.messages.actions.create.notice`
185
+
186
+ By default support the actions: `create`, `update` and `delete`, but you can add more actions to translate
187
+
188
+ You can add translation based on models, changing the `action` key for your model name. Example:
189
+ `mini_api.messages.model_name.create.alert`. With this, is more easy personalize messages
190
+
191
+ ### Transform keys
192
+
193
+ 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`
194
+
195
+ To change the transform operation, simply adds a initializer on initilizations folder with content:
196
+ ```ruby
197
+ MiniApi::Config.configure do |config|
198
+ config.transform_params_keys_to = :snake_case
199
+ config.transform_response_keys_to = :camel_lower
200
+ end
201
+ ```
202
+ The option `transform_params_keys_to` will transform request params.
203
+ The option `transform_response_keys_to` will transform responses.
204
+
144
205
  ## Overriding response
145
206
 
146
207
  You can override the `status`, `message` and `sucess` keys simply informing values to `render_json`. Example:
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mini_api/config'
4
+ require 'mini_api/exceptions/case_transform_option_invalid'
5
+
6
+ module MiniApi
7
+ module CaseTransform
8
+ module_function
9
+
10
+ def transform(object, transform_to = :snake_case)
11
+ object.deep_transform_keys do |key|
12
+ case transform_to
13
+ when :camel_case
14
+ key.to_s.camelize
15
+ when :camel_lower
16
+ key.to_s.camelize(:lower)
17
+ when :snake_case
18
+ key.to_s.underscore
19
+ else
20
+ raise CaseTransformOptionInvalid, "option #{transform_to} is not supported."
21
+ end
22
+ end
23
+ end
24
+
25
+ def request_params_keys(params)
26
+ transform(params, Config.transform_params_keys_to)
27
+ end
28
+
29
+ def response_keys(response)
30
+ transform(response, Config.transform_response_keys_to)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniApi
4
+ class Config
5
+ include ActiveSupport::Configurable
6
+
7
+ # permitted values are: [:camel_case, :camel_lower, snake_case]
8
+ config_accessor :transform_params_keys_to, instance_accessor: false, default: :snake_case
9
+ config_accessor :transform_response_keys_to, instance_accessor: false, default: :snake_case
10
+ end
11
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'mini_api/case_transform'
4
+
3
5
  module MiniApi
4
6
  class DefaultResponder
5
7
  def initialize(controller, resource, options = {})
@@ -11,14 +13,39 @@ module MiniApi
11
13
  def respond
12
14
  success = @options[:success] != false
13
15
 
16
+ data = transform_keys
17
+
18
+ body =
19
+ if success
20
+ { data: data }
21
+ else
22
+ { errors: data }
23
+ end
24
+
14
25
  @controller.render(
15
26
  json: {
16
27
  success: success,
17
- data: @resource,
18
- message: @options[:message] || nil
28
+ message: @options[:message] || nil,
29
+ **body
19
30
  },
20
31
  status: @options[:status] || :ok
21
32
  )
22
33
  end
34
+
35
+ private
36
+
37
+ def transform_keys
38
+ return CaseTransform.response_keys(@resource) if @resource.is_a?(Hash)
39
+
40
+ return @resource unless @resource.is_a?(Array)
41
+
42
+ @resource.map do |item|
43
+ if item.is_a?(Hash)
44
+ CaseTransform.response_keys(item)
45
+ else
46
+ item
47
+ end
48
+ end
49
+ end
23
50
  end
24
51
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniApi
4
+ class CaseTransformOptionInvalid < StandardError; end
5
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'mini_api/serialization'
4
+ require 'mini_api/case_transform'
4
5
 
5
6
  module MiniApi
6
7
  # class to handle json render of ActiveRecord::Base instances and ActiveModel::Model's
@@ -21,7 +22,7 @@ module MiniApi
21
22
 
22
23
  body =
23
24
  if resource_has_errors?
24
- { errors: @resource.errors.messages }.merge(body)
25
+ errors.merge(body)
25
26
  else
26
27
  { data: serialiable_body(@resource).as_json }.merge(body)
27
28
  end
@@ -30,6 +31,8 @@ module MiniApi
30
31
  # attribute when resource is an ActiveModel instance
31
32
  body[:data] = body[:data].except('errors') if body[:data]&.key?('errors')
32
33
 
34
+ body = CaseTransform.response_keys(body)
35
+
33
36
  @controller.render json: body, status: status_code
34
37
  end
35
38
 
@@ -39,6 +42,14 @@ module MiniApi
39
42
  !@resource.errors.empty?
40
43
  end
41
44
 
45
+ def errors
46
+ error_serializer = get_error_serializer(@resource)
47
+
48
+ return { errors: @resource.errors.messages } unless error_serializer
49
+
50
+ { errors: error_serializer.new(@resource).as_json }
51
+ end
52
+
42
53
  def status_code
43
54
  return @options[:status] if @options[:status].present?
44
55
 
@@ -54,12 +65,23 @@ module MiniApi
54
65
  def default_message
55
66
  kind = resource_has_errors? ? 'alert' : 'notice'
56
67
 
57
- I18n.t(
58
- kind,
59
- scope: [:mini_api, :messages, :actions, @controller.action_name],
60
- resource_name: @resource.class.model_name.human,
61
- default: ''
62
- )
68
+ model_path = "mini_api.messages.#{@resource.model_name.i18n_key}"
69
+
70
+ if I18n.exists? model_path
71
+ I18n.t(
72
+ kind,
73
+ scope: "#{model_path}.#{@controller.action_name}",
74
+ resource_name: @resource.class.model_name.human,
75
+ default: ''
76
+ )
77
+ else
78
+ I18n.t(
79
+ kind,
80
+ scope: [:mini_api, :messages, :actions, @controller.action_name],
81
+ resource_name: @resource.class.model_name.human,
82
+ default: ''
83
+ )
84
+ end
63
85
  end
64
86
 
65
87
  def previously_new_record?
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'mini_api/exceptions/kaminari_not_installed'
4
4
  require 'mini_api/serialization'
5
+ require 'mini_api/case_transform'
5
6
 
6
7
  module MiniApi
7
8
  class RelationResponder
@@ -16,6 +17,10 @@ module MiniApi
16
17
  def respond
17
18
  meta, collection = extract_meta_and_collection
18
19
 
20
+ meta = CaseTransform.response_keys(meta)
21
+
22
+ collection = transform_case(collection.as_json)
23
+
19
24
  @controller.render json: {
20
25
  success: @options[:success] || true,
21
26
  data: collection,
@@ -40,6 +45,10 @@ module MiniApi
40
45
  ]
41
46
  end
42
47
 
48
+ def transform_case(collection)
49
+ collection.map { |item| CaseTransform.response_keys(item) }
50
+ end
51
+
43
52
  def transform_resource_to_collection
44
53
  unless defined?(Kaminari)
45
54
  raise KaminariNotInstalled, 'The Kaminari gem is not installed. Install to perform pagination operations'
@@ -12,5 +12,11 @@ module MiniApi
12
12
 
13
13
  @controller.get_serializer(resource)
14
14
  end
15
+
16
+ def get_error_serializer(resource)
17
+ serializer_class = @controller.get_serializer(resource)
18
+
19
+ "#{serializer_class.serializer}::Error".safe_constantize
20
+ end
15
21
  end
16
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniApi
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.4'
5
5
  end
data/lib/mini_api.rb CHANGED
@@ -2,9 +2,23 @@
2
2
 
3
3
  require 'mini_api/railtie'
4
4
  require 'mini_api/responder'
5
+ require 'mini_api/case_transform'
5
6
 
6
7
  # Entrypoint module
7
8
  module MiniApi
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include CaseTransform
13
+
14
+ before_action :transform_params
15
+
16
+ def transform_params
17
+ self.params =
18
+ ActionController::Parameters.new(CaseTransform.request_params_keys(request.parameters))
19
+ end
20
+ end
21
+
8
22
  def render_json(resource, options = {})
9
23
  responder = Responder.new(self, resource, options)
10
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
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-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -35,7 +35,10 @@ files:
35
35
  - README.md
36
36
  - Rakefile
37
37
  - lib/mini_api.rb
38
+ - lib/mini_api/case_transform.rb
39
+ - lib/mini_api/config.rb
38
40
  - lib/mini_api/default_responder.rb
41
+ - lib/mini_api/exceptions/case_transform_option_invalid.rb
39
42
  - lib/mini_api/exceptions/kaminari_not_installed.rb
40
43
  - lib/mini_api/locales/en.yml
41
44
  - lib/mini_api/model_responder.rb