mini_api 0.1.2 → 0.1.4

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: 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