exception_handler 0.7.7.0 → 0.8.0.0

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.
Files changed (93) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +13 -3
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -2
  5. data/Gemfile +3 -0
  6. data/README.md +330 -124
  7. data/app/assets/stylesheets/exception_handler.css.erb +5 -0
  8. data/app/assets/stylesheets/styles/_base.css.erb +1 -8
  9. data/app/assets/stylesheets/styles/_exception.css.erb +2 -1
  10. data/app/controllers/exception_handler/exceptions_controller.rb +10 -3
  11. data/app/models/exception_handler/exception.rb +21 -20
  12. data/app/views/exception_handler/exceptions/show.html.erb +1 -1
  13. data/app/views/layouts/exception.html.erb +5 -0
  14. data/app/views/layouts/mailer.html.erb +5 -0
  15. data/app/views/layouts/mailer.text.erb +1 -0
  16. data/config/locales/exception_handler.en.yml +1 -1
  17. data/config/routes.rb +42 -0
  18. data/exception_handler.gemspec +9 -8
  19. data/lib/exception_handler.rb +1 -0
  20. data/lib/exception_handler/config.rb +109 -40
  21. data/lib/exception_handler/engine.rb +11 -3
  22. data/lib/exception_handler/version.rb +2 -2
  23. data/spec/controllers/controller_spec.rb +107 -0
  24. data/spec/dummy/.rspec +1 -0
  25. data/spec/dummy/.ruby-version +1 -0
  26. data/spec/dummy/Rakefile +6 -0
  27. data/spec/dummy/app/assets/config/manifest.js +3 -0
  28. data/spec/dummy/app/assets/images/.keep +0 -0
  29. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  30. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  31. data/spec/dummy/app/assets/javascripts/channels/.keep +0 -0
  32. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  33. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  34. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  35. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  36. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  37. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  38. data/spec/dummy/app/jobs/application_job.rb +2 -0
  39. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  40. data/spec/dummy/app/models/application_record.rb +3 -0
  41. data/spec/dummy/app/models/concerns/.keep +0 -0
  42. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  43. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  44. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  45. data/spec/dummy/bin/bundle +3 -0
  46. data/spec/dummy/bin/rails +4 -0
  47. data/spec/dummy/bin/rake +4 -0
  48. data/spec/dummy/bin/setup +36 -0
  49. data/spec/dummy/bin/update +31 -0
  50. data/spec/dummy/bin/yarn +11 -0
  51. data/spec/dummy/config.ru +5 -0
  52. data/spec/dummy/config/application.rb +18 -0
  53. data/spec/dummy/config/boot.rb +5 -0
  54. data/spec/dummy/config/cable.yml +10 -0
  55. data/spec/dummy/config/database.yml +25 -0
  56. data/spec/dummy/config/environment.rb +5 -0
  57. data/spec/dummy/config/environments/development.rb +61 -0
  58. data/spec/dummy/config/environments/production.rb +94 -0
  59. data/spec/dummy/config/environments/test.rb +46 -0
  60. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  61. data/spec/dummy/config/initializers/assets.rb +14 -0
  62. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
  64. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +16 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/spec/dummy/config/locales/en.yml +33 -0
  70. data/spec/dummy/config/puma.rb +34 -0
  71. data/spec/dummy/config/routes.rb +3 -0
  72. data/spec/dummy/config/storage.yml +34 -0
  73. data/spec/dummy/lib/assets/.keep +0 -0
  74. data/spec/dummy/log/.keep +0 -0
  75. data/spec/dummy/package.json +5 -0
  76. data/spec/dummy/public/404.html +67 -0
  77. data/spec/dummy/public/422.html +67 -0
  78. data/spec/dummy/public/500.html +66 -0
  79. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  80. data/spec/dummy/public/apple-touch-icon.png +0 -0
  81. data/spec/dummy/public/favicon.ico +0 -0
  82. data/spec/dummy/spec/rails_helper.rb +57 -0
  83. data/spec/dummy/spec/spec_helper.rb +100 -0
  84. data/spec/dummy/storage/.keep +0 -0
  85. data/spec/features/asset_spec.rb +61 -0
  86. data/spec/features/config_spec.rb +51 -0
  87. data/spec/features/engine_spec.rb +180 -0
  88. data/spec/routing/routing_spec.rb +85 -0
  89. data/spec/spec_helper.rb +93 -0
  90. data/spec/views/views_spec.rb +29 -0
  91. metadata +79 -6
  92. data/app/assets/images/exception_handler/bg.jpg +0 -0
  93. data/app/assets/images/exception_handler/bg_overlay.png +0 -0
@@ -15,4 +15,9 @@
15
15
  */
16
16
  /* ---------------------------------------------------- */
17
17
  /* ---------------------------------------------------- */
18
+ /*
19
+ *= link_tree ../images
20
+ */
21
+ /* ---------------------------------------------------- */
22
+ /* ---------------------------------------------------- */
18
23
  /* ---------------------------------------------------- */
@@ -4,19 +4,12 @@
4
4
  /* ---------------------------------------------------- */
5
5
  /* ---------------------------------------------------- */
6
6
 
7
- /*
8
- *= link_tree ../../images
9
- */
10
-
11
- /* ---------------------------------------------------- */
12
- /* ---------------------------------------------------- */
13
-
14
7
  * { margin: 0; }
15
8
  html, body { height: 100%; }
16
9
  html {
17
10
  height: 100%;
18
11
  color: #fff;
19
- background: #010008 url(<%= asset_url("exception_handler/bg.jpg") %>) top left no-repeat;
12
+ background: #121212;
20
13
  background-size: 100% 100%;
21
14
  box-sizing: border-box;
22
15
  }
@@ -53,7 +53,8 @@
53
53
  border-color: rgba(255,255,255,0.09);
54
54
  border-style: solid
55
55
  }
56
- .exception:hover { cursor: pointer; }
56
+ .exception:hover { cursor: pointer; }
57
+ .exception:hover:after { text-decoration: underline; }
57
58
 
58
59
  .exception span:before {
59
60
  display: block;
@@ -36,9 +36,11 @@ module ExceptionHandler
36
36
  layout :layout
37
37
 
38
38
  ####################
39
- # Action #
39
+ # Actions #
40
40
  ####################
41
41
 
42
+ # => General Show Functionality
43
+ # => Introduced new "action" config option in 0.8.0.0
42
44
  def show
43
45
  respond_with @exception, status: @exception.status
44
46
  end
@@ -48,8 +50,13 @@ module ExceptionHandler
48
50
 
49
51
  private
50
52
 
51
- def layout
52
- ExceptionHandler.config.layouts[@exception.status]
53
+ # => Pulls from Exception class
54
+ # => Spanner in the works is nil
55
+ # => .present? validates against empty strings (IE a string is present)
56
+ # => .nil? validates to see if the returned data is "nil"
57
+ # => nil required to facilitate inheritance of the layout w/ ApplicationController
58
+ def layout option = ExceptionHandler.config.options(@exception.status, :layout)
59
+ (option.present? || option.nil?) ? option : 'exception'
53
60
  end
54
61
 
55
62
  ##################################
@@ -10,20 +10,13 @@ module ExceptionHandler
10
10
  # => Attributes
11
11
  # => Determine schema etc
12
12
  ATTRS = %i(class_name status message trace target referrer params user_agent)
13
-
14
- # => Exceptions to be rescued by ExceptionHandler
15
- EXCEPTIONS_TO_BE_RESCUED = [ActionController::RoutingError, AbstractController::ActionNotFound].tap do |list|
16
- list << ActiveRecord::RecordNotFound if defined?(ActiveRecord)
17
- list << Mongoid::Errors::DocumentNotFound if defined?(Mongoid)
18
- end
19
13
 
20
14
  ############################################################
21
15
  ############################################################
22
16
 
23
17
  # => Class (inheritance dependent on whether db option is available)
24
- self::Exception = Class.new(
25
- (ExceptionHandler.config.try(:db) && defined?(ActiveRecord)) ? ActiveRecord::Base : Object
26
- ) do
18
+ self::Exception =
19
+ Class.new( (ExceptionHandler.config.try(:db) && defined?(ActiveRecord)) ? ActiveRecord::Base : Object ) do
27
20
 
28
21
  # => Include individual elements
29
22
  # => Only required if no db present (no ActiveRecord)
@@ -97,15 +90,14 @@ module ExceptionHandler
97
90
  # => Email
98
91
  # => after_initialize invoked after .new method called
99
92
  # => Should have been after_create but user may not save
100
- after_initialize Proc.new { |e| ExceptionHandler::ExceptionMailer.new_exception(e).deliver } if ExceptionHandler.config.try(:email).try(:is_a?, String)
93
+ after_initialize -> (e) { ExceptionHandler::ExceptionMailer.new_exception(e).deliver }, if: :email? # => see bottom of file
101
94
 
102
95
  # => Attributes
103
96
  attr_accessor :request, :klass, :exception, :description
104
97
  attr_accessor *ATTRS unless ExceptionHandler.config.try(:db)
105
98
 
106
99
  # => Validations
107
- validates :klass, exclusion: { in: EXCEPTIONS_TO_BE_RESCUED, message: "%{value}" }, if: -> { referer.blank? } # => might need full Proc syntax
108
- validates :user_agent, format: { without: Regexp.new( BOTS.join("|"), Regexp::IGNORECASE ) }
100
+ validates :user_agent, format: { without: Regexp.new( BOTS.join("|"), Regexp::IGNORECASE ) }
109
101
 
110
102
  ##################################
111
103
  ##################################
@@ -114,21 +106,22 @@ module ExceptionHandler
114
106
  # Virtual
115
107
  ####################################
116
108
 
109
+ # => Exception (virtual)
110
+ # => Basis on which all the class is built
111
+ def exception
112
+ request.env['action_dispatch.exception']
113
+ end
114
+
117
115
  # => Klass
118
116
  # => Used for validation (needs to be cleaned up in 0.7.0)
119
117
  def klass
120
118
  exception.class
121
119
  end
122
120
 
123
- # => Exception (virtual)
124
- def exception
125
- request.env['action_dispatch.exception']
126
- end
127
-
128
121
  # => Description
129
122
  def description
130
123
  I18n.with_options scope: [:exception_handler], message: message, status: status do |i18n|
131
- i18n.t response, default: Rack::Utils::HTTP_STATUS_CODES[status] || status
124
+ i18n.t response, default: Rack::Utils::HTTP_STATUS_CODES[status]
132
125
  end
133
126
  end
134
127
 
@@ -143,7 +136,7 @@ module ExceptionHandler
143
136
 
144
137
  # => Message
145
138
  def message
146
- exception.message
139
+ exception ? exception.message : Rack::Utils::HTTP_STATUS_CODES[status]
147
140
  end
148
141
 
149
142
  # => Trace
@@ -181,7 +174,7 @@ module ExceptionHandler
181
174
 
182
175
  # => Status code (404, 500 etc)
183
176
  def status
184
- ActionDispatch::ExceptionWrapper.new(request.env, exception).status_code
177
+ exception ? ActionDispatch::ExceptionWrapper.new(request.env, exception).try(:status_code) : request.env["PATH_INFO"][1..-1].to_i
185
178
  end
186
179
 
187
180
  # => Server Response ("Not Found" etc)
@@ -192,6 +185,14 @@ module ExceptionHandler
192
185
  ##################################
193
186
  ##################################
194
187
 
188
+ private
189
+
190
+ # => Email
191
+ # => should be on the same line as after_initialize but too long
192
+ def email?
193
+ ExceptionHandler.config.try(:email).try(:is_a?, String) && ExceptionHandler.config.options(status, :notification) != false
194
+ end
195
+
195
196
  end
196
197
  end
197
198
 
@@ -1,3 +1,3 @@
1
- <%= content_tag :div, class: "exception", data: { status: @exception.status, response: @exception.response.to_s.humanize, rails: Rails.version }, onclick: ("location.href=\"#{root_url}\";" if @exception.status == "500" && Rails.application.routes.recognize_path("/")), title: ("Return Home" if @exception.status == "500" && Rails.application.routes.recognize_path("/")) do %>
1
+ <%= content_tag :div, class: "exception", data: { status: @exception.status, response: @exception.response.to_s.humanize, rails: Rails.version }, onclick: ("location.href=\"#{root_url}\";" if @exception.status.to_s.first == "5" && Rails.application.routes.recognize_path("/")) do %>
2
2
  <%= content_tag :span, @exception.description.html_safe %>
3
3
  <% end %>
@@ -9,6 +9,10 @@
9
9
  <%= stylesheet_link_tag :exception_handler %>
10
10
  <%= favicon_link_tag "exception_handler/favicon.ico" %>
11
11
 
12
+ <% if x = ExceptionHandler.config.options(@exception.status) %>
13
+ <style>body { background: url("<%= asset_path x %>") center center no-repeat !important; background-size: cover !important; }</style>
14
+ <% end %>
15
+
12
16
  <!-- Auth -->
13
17
  <%= csrf_meta_tags %>
14
18
  </head>
@@ -24,4 +28,5 @@
24
28
  <% end %>
25
29
  <% end %>
26
30
  <% end %>
31
+
27
32
  </html>
@@ -0,0 +1,5 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head><meta content="text/html; charset=utf-8" http-equiv="Content-Type" /></head>
4
+ <body><%= yield %></body>
5
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -22,7 +22,7 @@
22
22
 
23
23
  en:
24
24
  exception_handler:
25
- internal_server_error: "<strong>%{status} Error</strong> %{message} <p>Return home</p>"
25
+ internal_server_error: "<strong>%{status} Error</strong> %{message}"
26
26
 
27
27
  #######################################################################################
28
28
  #######################################################################################
@@ -0,0 +1,42 @@
1
+ ########################################
2
+ ########################################
3
+ ## _____ _ ##
4
+ ## | ___ \ | | ##
5
+ ## | |_/ /___ _ _| |_ ___ ___ ##
6
+ ## | // _ \| | | | __/ _ \/ __| ##
7
+ ## | |\ \ (_) | |_| | || __/\__ \ ##
8
+ ## \_| \_\___/ \__,_|\__\___||___/ ##
9
+ ## ##
10
+ ########################################
11
+ ########################################
12
+
13
+ ## Good resource
14
+ ## https://gist.github.com/maxivak/5d428ade54828836e6b6#merge-engine-and-app-routes
15
+
16
+ ########################################
17
+ ########################################
18
+
19
+ ## Routes ##
20
+ Rails.application.routes.draw do
21
+
22
+ ########################################
23
+ ########################################
24
+
25
+ # => ExceptionHandler
26
+ # => Used to provide error page examples in "dev" mode
27
+ if Object.const_defined?('ExceptionHandler') && ExceptionHandler.config.try(:dev)
28
+
29
+ # => Items
30
+ Rack::Utils::SYMBOL_TO_STATUS_CODE.select{ |key, value| value.to_s.match('\b(?:4[0-9]{2}|5[0-9]{2}|599)\b') }.each do |code, status|
31
+ get status.to_s, to: 'exception_handler/exceptions#show', as: code, code: code
32
+ end
33
+
34
+ end
35
+
36
+ ########################################
37
+ ########################################
38
+
39
+ end
40
+
41
+ ########################################
42
+ ########################################
@@ -11,16 +11,17 @@ require_relative 'lib/exception_handler/version'
11
11
  Gem::Specification.new do |s|
12
12
 
13
13
  ## General ##
14
- s.name = "exception_handler"
15
- s.authors = ["R.Peck"]
16
- s.email = ["rpeck@fl.co.uk"]
17
- s.version = ExceptionHandler::VERSION::STRING
18
- s.platform = Gem::Platform::RUBY
14
+ s.name = "exception_handler"
15
+ s.authors = ["R.Peck"]
16
+ s.email = ["rpeck@fl.co.uk"]
17
+ s.version = ExceptionHandler::VERSION::STRING
18
+ s.platform = Gem::Platform::RUBY
19
19
 
20
20
  ## Details ##
21
- s.summary = %q{Rails gem to show custom error pages in production. Also logs errors in db & sends notification emails}
22
- s.description = %q{Rails gem to create custom error pages. Captures exceptions using "exception_app" callback, routing to "Exception" controller, rendering the view as required.}
23
- s.homepage = "https://github.com/richpeck/exception_handler"
21
+ s.summary = %q{Rails gem to show custom error pages in production. Also logs errors in db & sends notification emails}
22
+ s.description = %q{Rails gem to create custom error pages. Captures exceptions using "exception_app" callback, routing to "Exception" controller, rendering the view as required.}
23
+ s.post_install_message = %q{ExceptionHandler 0.8.0.0 → New "config" (config.exception_handler = {exceptions: {layout: 'x', notification: true, action: {redirect_to root_path} }} ). https://www.github.com/richpeck/exception_handler#config for more info. }
24
+ s.homepage = "https://github.com/richpeck/exception_handler"
24
25
 
25
26
  ## License ##
26
27
  s.license = "MIT"
@@ -37,6 +37,7 @@ module ExceptionHandler
37
37
  ##############################
38
38
  ##############################
39
39
 
40
+
40
41
  end
41
42
 
42
43
  #########################################################
@@ -7,7 +7,7 @@
7
7
  ## | \__/\ (_) | | | | | | | (_| | ##
8
8
  ## \____/\___/|_| |_|_| |_|\__, | ##
9
9
  ## __/ | ##
10
- ## |___/ ##
10
+ ## |___/ ##
11
11
  ###########################################
12
12
  ###########################################
13
13
 
@@ -26,9 +26,10 @@ module ExceptionHandler
26
26
  # => ExceptionHandler.config.db
27
27
  # => ExceptionHandler.config.email
28
28
  # => ExceptionHandler.config.social
29
- # => ExceptionHandler.config.layouts
29
+ # => ExceptionHandler.config.layouts -> will need to be deprecated
30
+ # => ExceptionHandler.config.exceptions
30
31
  # => ExceptionHandler.config.custom_exceptions
31
- attr_accessor :dev, :db, :email, :social, :layouts, :custom_exceptions
32
+ attr_accessor :dev, :db, :email, :social, :layouts, :exceptions, :custom_exceptions
32
33
 
33
34
  ###########################################
34
35
  ###########################################
@@ -39,51 +40,96 @@ module ExceptionHandler
39
40
  # => Has to be "errors" because "exceptions" is a reserved word
40
41
  TABLE = :errors
41
42
 
43
+ ###########################################
44
+ ###########################################
45
+
42
46
  # => Social URLs
43
47
  # => Extracted from "social" block
44
- SOCIAL = {
45
- facebook: "https://facebook.com",
46
- twitter: "https://twitter.com",
47
- youtube: "https://youtube.com/user",
48
- linkedin: "https://linkedin.com/company",
49
- fusion: "https://frontlinefusion.com"
50
- }
48
+ SOCIAL =
49
+ ActiveSupport::HashWithIndifferentAccess.new({
50
+ facebook: "https://www.facebook.com",
51
+ twitter: "https://www.twitter.com",
52
+ youtube: "https://www.youtube.com/user",
53
+ linkedin: "https://www.linkedin.com/company",
54
+ fusion: "https://www.frontlinefusion.com"
55
+ })
51
56
 
52
57
  ###########################################
53
58
  ###########################################
54
59
 
55
60
  # => Defaults
56
61
  # => http://stackoverflow.com/a/8917301/1143732
57
- DEFAULTS = {
58
- dev: nil, # => defaults to "false" for dev mode
59
- db: nil, # => defaults to :errors if true, else use "table_name" / :table_name
60
- email: nil, # => requires string email and ActionMailer
61
- social: {
62
- facebook: nil,
63
- twitter: nil,
64
- youtube: nil,
65
- linkedin: nil,
66
- fusion: nil,
67
- },
68
- layouts: {
69
- # => nil inherits from ApplicationController
70
- # => 4xx errors should be nil
71
- # => 5xx errors should be "exception" but can be nil if explicitly defined
72
- 500 => "exception",
73
- 501 => "exception",
74
- 502 => "exception",
75
- 503 => "exception",
76
- 504 => "exception",
77
- 505 => "exception",
78
- 507 => "exception",
79
- 510 => "exception"
80
- }
81
- }
82
-
83
- ###########################################
84
- ###########################################
85
-
86
- # => Init
62
+ DEFAULTS =
63
+ ActiveSupport::HashWithIndifferentAccess.new({
64
+
65
+ # => General options
66
+ dev: nil, # => defaults to "false" for dev mode
67
+ db: nil, # => defaults to :errors if true, else use "table_name" / :table_name
68
+ email: nil, # => requires string email and ActionMailer
69
+
70
+ # => Used in "exception" layout
71
+ social: {
72
+ facebook: nil,
73
+ twitter: nil,
74
+ youtube: nil,
75
+ linkedin: nil,
76
+ fusion: nil,
77
+ },
78
+
79
+ # => Defaults for exceptions. Override with specific status codes
80
+ # => Please note these are all STRINGS
81
+ exceptions: {
82
+
83
+ # => 4xx/5xx base standard
84
+ # => :all provide block customization (overrides 4xx/5xx)
85
+ # => specific provides individual (overrides all)
86
+
87
+ # => 4xx Errors (resource not found)
88
+ # => https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_errors
89
+ '4xx' => {
90
+ layout: nil
91
+ # notification: true #(this is for emails - it's true by default - only if you have email inputted)
92
+ # action: ____, (this is general)
93
+ # background: (can define custom background for exceptions layout if required)
94
+ },
95
+
96
+ # => 5xx Errors (server error)
97
+ # => https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_Server_errors
98
+ '5xx' => {
99
+ layout: 'exception'
100
+ # notification: true (this is for emails - it's true by default - only if you have email inputted)
101
+ # action: _____, (this is general)
102
+ # background: (can define custom background for exceptions layout if required)
103
+ }
104
+ },
105
+
106
+ # Deprecated
107
+ #layouts: {
108
+ # => nil inherits from ApplicationController
109
+ # => 4xx errors should be nil
110
+ # => 5xx errors should be "exception" but can be nil if explicitly defined
111
+ #500 => 'exception',
112
+ #501 => 'exception',
113
+ #502 => 'exception',
114
+ #503 => 'exception',
115
+ #504 => 'exception',
116
+ #505 => 'exception',
117
+ #507 => 'exception',
118
+ #510 => 'exception'
119
+ #},
120
+
121
+ # => If you want to map your own classes to HTTP errors
122
+ # => use this...
123
+ custom_exceptions: {
124
+ #'ActionController::RoutingError' => :not_found # => example
125
+ }
126
+
127
+ })
128
+
129
+ ###########################################
130
+ ###########################################
131
+
132
+ # => Constructor
87
133
  # => Merges DEFAULTS to values, creates instances vars (for attr_accessor)
88
134
  def initialize values
89
135
 
@@ -107,6 +153,29 @@ module ExceptionHandler
107
153
  @db == true ? TABLE : @db.try(:parameterize, separator: "_")
108
154
  end
109
155
 
156
+ ###########################################
157
+ ###########################################
158
+
159
+ # => Options
160
+ # => Requires argument
161
+ def options status, pluck=nil
162
+
163
+ # => Structure from old + new setup
164
+ # => 1. layouts => [500, '500']
165
+ # => 2. exceptions => [500, '500' 'all', '4xx'/'5xx']
166
+ { layouts: [status, status.to_s], # old + new
167
+ exceptions: [status, status.to_s, 'all', status.to_s.first + 'xx'] }.each do |key,array|
168
+
169
+ # => Array
170
+ # => https://stackoverflow.com/a/26877095/1143732
171
+ array.each do |specific|
172
+ item = self.send(key).try(:[], specific)
173
+ return (item.is_a?(Hash) ? ActiveSupport::HashWithIndifferentAccess.new(item)[pluck.try(:to_sym)] : item) if item.present? || (self.send(key).try(:has_key?, specific) && item.nil?) #if result exists and it has a value (including nil)
174
+ end
175
+
176
+ end
177
+ end
178
+
110
179
  ###########################################
111
180
  ###########################################
112
181
  ###########################################