otpor 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/otpor/active_record_validation_error.rb +22 -0
- data/lib/otpor/json_response.rb +124 -0
- data/lib/otpor/templates/shared/response.json.jbuilder +14 -0
- data/lib/otpor/version.rb +5 -0
- data/lib/otpor.rb +16 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d65aa7219b3a7e0218aceb14abc70ffa459989de2421eb8dddf56eb9e902462f
|
4
|
+
data.tar.gz: 491bb18692f97fe0525c01f87ba99a89f78576208b8fa16e2d35eb92d90808e7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bedbe5c976532ce83c83ee2e99d864cf9be6f223ac2834d382791128a09022ec4fab145e728c980b819b25900390989a5f66cde56b3587cca37346f2e44cbe81
|
7
|
+
data.tar.gz: 55b496f6d2b6bfb4d56f3a92f7e0456d6741d941cf53764357ae53cbe1f6705d6088df1a0d50b850c43db7b19c13fded9a7c7d37dc862de5d89c725cb33b433e
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Otpor
|
2
|
+
module ActiveRecordValidationError
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
after_validation :log_validation_errors, if: -> { errors.any? }
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def log_validation_errors
|
12
|
+
error_messages = []
|
13
|
+
errors.each do |error|
|
14
|
+
error_messages << { attribute: error.attribute, message: error.message, type: error.options.dig(:type) || error.type, entity: self.class.name, entity_id: self.id || 'new record'}
|
15
|
+
end
|
16
|
+
return unless error_messages.present?
|
17
|
+
|
18
|
+
RequestStore.store[:errors] ||= error_messages
|
19
|
+
RequestStore.store[:status_symbol] ||= :unprocessable_content
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Otpor
|
2
|
+
module JsonResponse
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
before_action :capture_initial_instance_variables
|
7
|
+
around_action :rescue_exceptions
|
8
|
+
rescue_from ActionView::MissingTemplate, with: :handle_missing_partial
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle_missing_partial; end
|
12
|
+
|
13
|
+
def default_render(*args)
|
14
|
+
super and return unless request.format.json?
|
15
|
+
|
16
|
+
@errors ||= RequestStore.store[:errors] || nil
|
17
|
+
@notes ||= nil
|
18
|
+
|
19
|
+
@status_symbol = RequestStore.store[:status_symbol] if RequestStore.store[:status_symbol]
|
20
|
+
@status_code = Rack::Utils::SYMBOL_TO_STATUS_CODE[@status_symbol] if @status_symbol
|
21
|
+
@status_code ||= response.status
|
22
|
+
@status = {
|
23
|
+
name: http_status_name(@status_code),
|
24
|
+
code: @status_code,
|
25
|
+
type: http_status_type(@status_code)
|
26
|
+
}
|
27
|
+
|
28
|
+
partial_exists = lookup_context.exists?("#{controller_path}/#{action_name}", [], true)
|
29
|
+
|
30
|
+
@data_partial ||= "#{controller_path}/#{action_name}" if @status[:type].eql?("Success") && partial_exists
|
31
|
+
|
32
|
+
@instance_variables = capture_new_instance_variables
|
33
|
+
|
34
|
+
@meta ||= infer_meta
|
35
|
+
|
36
|
+
render template: "shared/response", formats: :json, status: @status_code
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def http_status_name(status_code)
|
42
|
+
Rack::Utils::HTTP_STATUS_CODES[status_code]
|
43
|
+
end
|
44
|
+
|
45
|
+
def rescue_exceptions
|
46
|
+
yield
|
47
|
+
rescue StandardError => e
|
48
|
+
@status_code = determine_status_code(e)
|
49
|
+
@status = {
|
50
|
+
name: http_status_name(@status_code),
|
51
|
+
code: @status_code,
|
52
|
+
type: http_status_type(@status_code)
|
53
|
+
}
|
54
|
+
@errors ||= RequestStore.store[:errors] || nil
|
55
|
+
@exception_log = [{ message: e.message, backtrace: e.backtrace[0, 5] }] if Rails.env.development?
|
56
|
+
render template: "shared/response", formats: :json, status: @status_code
|
57
|
+
end
|
58
|
+
|
59
|
+
def determine_status_code(exception)
|
60
|
+
case exception
|
61
|
+
when ActiveRecord::RecordNotFound
|
62
|
+
404
|
63
|
+
when ActionController::RoutingError, ActionController::UnknownFormat
|
64
|
+
404
|
65
|
+
when ActiveRecord::RecordInvalid, ActionController::ParameterMissing
|
66
|
+
422
|
67
|
+
else
|
68
|
+
500
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def http_status_type(status_code)
|
73
|
+
case status_code
|
74
|
+
when 100..199
|
75
|
+
"Informational"
|
76
|
+
when 200..299
|
77
|
+
"Success"
|
78
|
+
when 300..399
|
79
|
+
"Redirection"
|
80
|
+
when 400..499
|
81
|
+
"Client Error"
|
82
|
+
when 500..599
|
83
|
+
"Server Error"
|
84
|
+
else
|
85
|
+
"Unknown"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def capture_initial_instance_variables
|
90
|
+
@initial_instance_variables = instance_variables
|
91
|
+
end
|
92
|
+
|
93
|
+
def capture_new_instance_variables
|
94
|
+
current_instance_variables = instance_variables
|
95
|
+
new_vars = current_instance_variables - @initial_instance_variables
|
96
|
+
new_vars -= %i[@initial_instance_variables @errors @notes @data_partial @status
|
97
|
+
@_response_body @new_instance_variables]
|
98
|
+
new_instance_vars = {}
|
99
|
+
new_vars.each do |var|
|
100
|
+
new_instance_vars[var] = instance_variable_get(var)
|
101
|
+
end
|
102
|
+
new_instance_vars
|
103
|
+
end
|
104
|
+
|
105
|
+
def infer_meta
|
106
|
+
@instance_variables.each do |key, value|
|
107
|
+
next unless value.respond_to?(:total_pages)
|
108
|
+
|
109
|
+
return {
|
110
|
+
pagination: {
|
111
|
+
total_pages: value.total_pages,
|
112
|
+
total_count: value.total_count,
|
113
|
+
current_page: value.current_page,
|
114
|
+
next_page: value.next_page,
|
115
|
+
prev_page: value.prev_page,
|
116
|
+
per_page: value.limit_value
|
117
|
+
}
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
json.status do
|
2
|
+
json.name @status[:name]
|
3
|
+
json.code @status[:code]
|
4
|
+
json.type @status[:type]
|
5
|
+
end
|
6
|
+
|
7
|
+
json.data do
|
8
|
+
json.partial! @data_partial if @data_partial.present?
|
9
|
+
end
|
10
|
+
|
11
|
+
json.errors @errors
|
12
|
+
json.notes @notes
|
13
|
+
json.meta @meta
|
14
|
+
json.exception_log @exception_log
|
data/lib/otpor.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "request_store"
|
4
|
+
require_relative "otpor/version"
|
5
|
+
require_relative "otpor/json_response"
|
6
|
+
require_relative "otpor/active_record_validation_error"
|
7
|
+
|
8
|
+
module Otpor
|
9
|
+
class Engine < ::Rails::Engine
|
10
|
+
initializer "otpor.load_view_paths" do |app|
|
11
|
+
ActiveSupport.on_load(:action_controller) do
|
12
|
+
append_view_path Otpor::Engine.root.join("lib", "otpor", "templates")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: otpor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Renan Garcia
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: kaminari
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.2.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: jbuilder
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.12.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.12.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: request_store
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: This gem includes a concern that defines a default Jbuilder template
|
98
|
+
for controller actions that include it, rendering consistent JSON responses.
|
99
|
+
email:
|
100
|
+
- renan.almeida.garcia@icloud.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- lib/otpor.rb
|
106
|
+
- lib/otpor/active_record_validation_error.rb
|
107
|
+
- lib/otpor/json_response.rb
|
108
|
+
- lib/otpor/templates/shared/response.json.jbuilder
|
109
|
+
- lib/otpor/version.rb
|
110
|
+
homepage: https://github.com/renan-garcia/otpor
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.5.17
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: 'Otpor: JSON Response Concern'
|
133
|
+
test_files: []
|