steroids 1.0.0 → 1.6.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +854 -0
  3. data/Rakefile +27 -0
  4. data/app/jobs/steroids/async_service_job.rb +10 -0
  5. data/app/serializers/steroids/error_serializer.rb +35 -0
  6. data/lib/resources/quotes.yml +114 -0
  7. data/lib/steroids/controllers/methods.rb +18 -0
  8. data/lib/{concerns/controller.rb → steroids/controllers/responders_helper.rb} +20 -21
  9. data/lib/steroids/controllers/serializers_helper.rb +15 -0
  10. data/lib/steroids/engine.rb +6 -0
  11. data/lib/steroids/errors/base.rb +57 -0
  12. data/lib/steroids/errors/context.rb +70 -0
  13. data/lib/steroids/errors/quotes.rb +29 -0
  14. data/lib/steroids/errors.rb +89 -0
  15. data/lib/steroids/extensions/array_extension.rb +25 -0
  16. data/lib/steroids/extensions/class_extension.rb +141 -0
  17. data/lib/steroids/extensions/hash_extension.rb +14 -0
  18. data/lib/steroids/extensions/method_extension.rb +63 -0
  19. data/lib/steroids/extensions/module_extension.rb +32 -0
  20. data/lib/steroids/extensions/object_extension.rb +122 -0
  21. data/lib/steroids/extensions/proc_extension.rb +9 -0
  22. data/lib/steroids/logger.rb +162 -0
  23. data/lib/steroids/railtie.rb +60 -0
  24. data/lib/steroids/serializers/base.rb +7 -0
  25. data/lib/{concerns/serializer.rb → steroids/serializers/methods.rb} +3 -3
  26. data/lib/steroids/services/base.rb +181 -0
  27. data/lib/steroids/support/magic_class.rb +17 -0
  28. data/lib/steroids/support/noticable_methods.rb +134 -0
  29. data/lib/steroids/support/servicable_methods.rb +34 -0
  30. data/lib/{base/type.rb → steroids/types/base.rb} +3 -3
  31. data/lib/{base/model.rb → steroids/types/serializable_type.rb} +2 -2
  32. data/lib/steroids/version.rb +4 -0
  33. data/lib/steroids.rb +12 -0
  34. metadata +75 -34
  35. data/lib/base/class.rb +0 -15
  36. data/lib/base/error.rb +0 -87
  37. data/lib/base/hash.rb +0 -49
  38. data/lib/base/list.rb +0 -51
  39. data/lib/base/service.rb +0 -104
  40. data/lib/concern.rb +0 -130
  41. data/lib/concerns/error.rb +0 -20
  42. data/lib/concerns/model.rb +0 -9
  43. data/lib/errors/bad_request_error.rb +0 -15
  44. data/lib/errors/conflict_error.rb +0 -15
  45. data/lib/errors/forbidden_error.rb +0 -15
  46. data/lib/errors/generic_error.rb +0 -14
  47. data/lib/errors/internal_server_error.rb +0 -15
  48. data/lib/errors/not_found_error.rb +0 -15
  49. data/lib/errors/not_implemented_error.rb +0 -15
  50. data/lib/errors/unauthorized_error.rb +0 -15
  51. data/lib/errors/unprocessable_entity_error.rb +0 -15
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ p 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Steroids'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,10 @@
1
+ module Steroids
2
+ class AsyncServiceJob < ApplicationJob
3
+ queue_as Rails.application.config.active_job.queue_adapter
4
+
5
+ def perform(class_name:, params:)
6
+ service = class_name.constantize
7
+ service.new(**params).call
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ module Steroids
2
+ class ErrorSerializer < Steroids::Serializers::Base
3
+ attribute :id
4
+ attribute :code
5
+ attribute :status
6
+ attribute :message
7
+ attribute :quote
8
+ attribute :errors
9
+ attribute :timestamp
10
+
11
+ attributes :exception,
12
+ :message,
13
+ if: -> { Rails.env.development? }
14
+
15
+ def exception
16
+ if @object.respond_to?(:cause) && @object.cause.present?
17
+ @object.cause.class.to_s&.demodulize
18
+ else
19
+ @object.class.to_s&.demodulize
20
+ end
21
+ end
22
+
23
+ def message
24
+ [
25
+ @object.message,
26
+ Rails.env.development? && @object.respond_to?(:cause) && @object.cause.present? ?
27
+ @object.cause : nil
28
+ ].compact.join(" - Cause by: ")
29
+ end
30
+
31
+ def timestamp
32
+ @object.timestamp
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,114 @@
1
+ - Dance like nobody is watching, code like everybody is."
2
+ - "A deployed MVP is worth two prototyped."
3
+ - "When you reach bearded-level, there are at least a hundred grey-beards above you."
4
+ - "A/B Test twice, deploy changes once."
5
+ - "Don't commit on master when drunk."
6
+ - "Sleep on a force push."
7
+ - "T_PAAMAYIM_NEKUDOTAYIM"
8
+ - "SEGMENTATION_FAULT"
9
+ - "A git pull a day, keeps the doctor away."
10
+ - "Sometimes you have to cut legacy support to allow the new product to bloom."
11
+ - "More hours worked, more commits made. Mostly reverts and bug-causing features."
12
+ - "Even a greybeard will drop production DB."
13
+ - "Scope creep makes a mountain."
14
+ - "A hundred programmers won't make a two-year project in a week."
15
+ - "Facebook wasn't built in a day."
16
+ - "Just ship is no substitute for design."
17
+ - "Today's fashion is tomorrow's legacy."
18
+ - "Learning obscure and strange languages, yields better understanding and broader horizons."
19
+ - "The better job you do, the easier others discount the level of difficulty."
20
+ - "Testing is easier than debugging."
21
+ - "Finish a product in a day, and people will expect a new product every day. Teach people about proper development cycles, and your company will flourish."
22
+ - "Customers are the best testers."
23
+ - "Absence is beauty, in error logs."
24
+ - "Eternal sunshine of the stateless mind."
25
+ - "Laziness is your best friend. Never do twice what you can automate once."
26
+ - "Good test coverage + automated workflows = quiet cell phones and better sleep."
27
+ - "The best code is no code at all."
28
+ - "The best request is the one you don't make."
29
+ - "If a system works perfectly, no one will care what is inside it. Once it breaks, systems design and architecture decides your fate."
30
+ - "Leave architecture for applications that require long-term support."
31
+ - "Architecture and design are preparations for problems and changes, not a key to runtime."
32
+ - "Without a prototype, don't build a final product."
33
+ - "Without boilerplate, there's no speedy development."
34
+ - "Code frustration is a bad advisor for a refactor."
35
+ - "The more technology you learn, the more you realize how little you know."
36
+ - "An early BETA launch will teach you more than a delayed promise."
37
+ - "All applications are pretty when your screen is off."
38
+ - "Do not pick a framework for its demo page, instead pick it for its code."
39
+ - "You cannot set a web standard alone."
40
+ - "A poor programmer blames the language."
41
+ - "The code's writin' but ain't nobody programming."
42
+ - "Mañana often has the most tickets."
43
+ - "Never optimize before measuring"
44
+ - "Think about your dance moves when drunk, next time you try to code with some beers on your count."
45
+ - "What happens in Git stays in Git"
46
+ - "Simpler code has less bugs."
47
+ - "Lock up your dependency versions and other valuables."
48
+ - "Quantity of attempts often yields quality at the end. Commitment to refactoring legacy code yields better quality yet."
49
+ - "Accept that some days you're the QA and some days you're the one fixing bugs."
50
+ - "Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude"
51
+ - "Debugging becomes significantly easier if you first admit that you are the problem."
52
+ - "Figure out your data structures, and the code will follow."
53
+ - "One thing should never do more than one thing."
54
+ - "Success from a final version is a lie, there is only iteration. Through iteration, we gain better products. Through better products, we gain traction. Through traction, we gain success. Through success, misguided tech specs are broken. The development cycle shall free us."
55
+ - "An open source developer does not act for personal fame."
56
+ - "Public code review forces one to better oneself. It forces better practices, smarter solutions, growth as a developer... or being broken."
57
+ - "Testing covers not testing."
58
+ - "The most attractive pull requests are the ones wearing a lot of red."
59
+ - "Coding styleguides without peer code reviews are like running a country on voluntary taxes"
60
+ - "Deploying an unmonitored app is like going on a roadtrip without a gas gauge."
61
+ - "Learn a programming language, become a new developer."
62
+ - "Some old code never refactors, and breaks at the slightest change."
63
+ - "A developer will spot a peer from far away"
64
+ - "A developer that codes until burnout, lives without a mind."
65
+ - "A marketer is not a QA, a developer does not advertise."
66
+ - "A soft spoken developer will see his warnings of technical debt unheeded, and will suffer the blame."
67
+ - "A well spoken developer can be hired hastily but at the last minute fail an easy test."
68
+ - "One can self-learn the art of code but do not assume other crafts suffer of such low bar of entry."
69
+ - "Find ease in your code; Code difficult to read and understand is code destined to be in troubled legacy."
70
+ - "Collaborating on open source projects can bring about friendship and community just as it can create factions and flame wars."
71
+ - "Refactor or rewrite, there is no patching unmaintainable legacy code"
72
+ - "If you stop learning now and take the easy path, you will find yourself stuck in legacy software forever."
73
+ - "A beautiful product which is pleasing to non-paying users is good only for frightening investors when it runs out of funding."
74
+ - "A foreach loop avoided is a CPU cycle earned."
75
+ - "You cannot prevent managers from asking too much of you, but you can prevent them from getting used to it."
76
+ - "Any sufficiently complex app architecture is indistinguishable from spaghetti code."
77
+ - "Writing requirements based code and walking on water are both relatively easy to do when frozen."
78
+ - "It takes twice as much intelligence to debug than to program, therefore you peer review because you can never truly be smart enough to debug your own code."
79
+ - "Hofstadter's Law will tell you to always add more time than you think you need to a project because it will take longer, even when you take into account Hofstadter's Law."
80
+ - "Long lasting code is written only when you pretend that it will be peer reviewed or maintained by a violent psycopath who knows where you live."
81
+ - "Small bug becomes a huge problem."
82
+ - "Commiting is the only command I know, Commiting on you."
83
+ - "Don't use `eval()` or unexpected bugs/horrible creatures from outer space might start popping-up."
84
+ - "After three days without programming, life becomes meaningless."
85
+ - "When the program is being tested, it is too late to make design changes."
86
+ - "When you have learned to snatch the error code from the trap frame, it will be time for you to leave."
87
+ - "A well-written program is its own heaven; a poorly-written program is its own hell."
88
+ - "Though a program be but three lines long, someday it will have to be maintained."
89
+ - "Let the programmer be many and the managers few - then all will be productive."
90
+ - "You can demonstrate a program for a corporate executive, but you can't make him computer literate."
91
+ - "Without the wind, the grass does not move. Without software, hardware is useless."
92
+ - "A problem has been detected and Windows has been shut down to prevent damage to your computer."
93
+ - "\"Fatal Exception 0E\" Error Message Attempting to Open Folder 176446 (Microsoft Internet Explorer for Win95)."
94
+ - "Fatal exception 0E has occurred at 0028:C02B9568 in VXD IFSMGR(04) + 00012AEC 273918 (running the Sysinternal Filemon.exe program during Win Me Setup.)"
95
+ - "NoMethodError (undefined method 'nil_class?' for nil:NilClass)"
96
+ - "When you send information to the Internet, it might be possible for others to see that information. Do you want to continue?"
97
+ - "Are you sure engineering is right for you? I heard the sales departement was looking for someone."
98
+ - "Out of memory error: Kill process, score, or sacrifice child."
99
+ - "Keyboard not responding. Press any key to continue."
100
+ - "Task failed successfully (no comments)."
101
+ - "Success! There was an error."
102
+ - "The “Delete” operation will erase the contents of your hard.drive. Proceed or delete?"
103
+ - "Something happened error, ¿but what?"
104
+ - "Windows Phone Installation Disc Error."
105
+ - "Guru Meditation error."
106
+ - "Abort, Retry, Fail?"
107
+ - "Critical error. All your files are exactly where you left them."
108
+ - "Your Password Must Be at Least 18770 Characters"
109
+ - "You are not authorized to view this error"
110
+ - "Never in the history of boredom has anyone been more bored than I am right now."
111
+ - "Artificial Intelligence usually beats natural stupidity."
112
+ - "To err is human... to really foul up requires the root password."
113
+ - "This problem exists between the chair and keyboard."
114
+ - "1f u c4n r34d th1s u r34lly n33d t0 g37 l41d"
@@ -0,0 +1,18 @@
1
+ module Steroids
2
+ module Controllers
3
+ module Methods
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include RespondersHelper
8
+ include SerializersHelper
9
+ include Support::ServicableMethods
10
+
11
+ def context
12
+ Rails.logger.warn('Using context is deprecated and will be removed.') unless Rails.env.production?
13
+ @context ||= ActiveSupport::HashWithIndifferentAccess.new
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,23 +1,30 @@
1
1
  module Steroids
2
- module Concerns
3
- module Controller
2
+ module Controllers
3
+ module RespondersHelper
4
4
  extend ActiveSupport::Concern
5
- included do
6
- before_action do
7
- context.add(params: params)
8
- end
9
5
 
6
+ included do
10
7
  protected
11
8
 
12
- def respond_with(data, options = {})
13
- options = __parse_options(data, options)
14
- data = __apply_scopes(data, options)
15
- data = __apply_pagination(data, options)
16
- return __response(data, options)
9
+ def respond_with(*resources, &block)
10
+ resource = resources.first
11
+ respond_to do | format |
12
+ format.json {
13
+ options = resources.extract_options!
14
+ options = __parse_options(resource, options)
15
+ scoped_data = __apply_scopes(resource, options)
16
+ paginated_data = __apply_pagination(scoped_data, options)
17
+ return __response(paginated_data, options)
18
+ }
19
+ format.any {
20
+ return defined?(super) ? super(*resources, &block) : resource
21
+ }
22
+ end
17
23
  end
18
24
 
19
25
  def context
20
- @context ||= Steroids::Base::Hash.new
26
+ Rails.logger.warn('Using context is deprecated and will be removed.') unless Rails.env.production?
27
+ @context ||= ActiveSupport::HashWithIndifferentAccess.new
21
28
  end
22
29
 
23
30
  private
@@ -53,20 +60,12 @@ module Steroids
53
60
  status = options[:status]
54
61
  if data
55
62
  options = options.merge({ json: data })
56
- options = options.merge(@context)
63
+ options = options.merge(@context || {})
57
64
  render(options)
58
65
  else
59
66
  status ? head(status) : raise(Steroids::Errors::NotFoundError)
60
67
  end
61
68
  end
62
-
63
- class << self
64
- attr_accessor :serializer
65
-
66
- def default_serializer(serializer)
67
- @serializer = serializer
68
- end
69
- end
70
69
  end
71
70
  end
72
71
  end
@@ -0,0 +1,15 @@
1
+ module Steroids
2
+ module Controllers
3
+ module SerializersHelper
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ attr_accessor :serializer
8
+
9
+ def default_serializer(serializer)
10
+ @serializer = serializer
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ module Steroids
3
+ class Engine < ::Rails::Engine
4
+ config.steroids = Steroids
5
+ end
6
+ end
@@ -0,0 +1,57 @@
1
+ module Steroids
2
+ module Errors
3
+ class Base < StandardError
4
+ include ActiveModel::Serialization
5
+ include Context
6
+ include Quotes
7
+
8
+ OTPIONS = %i[status message errors code cause context log]
9
+
10
+ class_attribute :default_message, default: "Oops, something went wrong (Unknown error)"
11
+ class_attribute :default_status, default: :internal_server_error
12
+
13
+ attr_reader :id, :message, :cause, :code, :status, :errors,
14
+ :record, :context, :timestamp, :logged
15
+
16
+ def initialize(message_string = nil, **options)
17
+ @caller = caller
18
+ extended_options = options.select{|key|OTPIONS.include?(key)}
19
+ splat_options = options.select{|key|!OTPIONS.include?(key)}
20
+ define_instance_variables_for(message_string, **extended_options)
21
+ super(**splat_options, message: message, cause: @cause)
22
+ set_backtrace(@cause&.backtrace || backtrace_locations || caller)
23
+ extended_options.fetch(:log, false) ? self.log! : self.quiet_log
24
+ end
25
+
26
+ def to_json
27
+ Steroids::ErrorSerializer.new(self).to_json
28
+ end
29
+
30
+ def log!
31
+ Steroids::Logger.print(self)
32
+ @logged = true
33
+ end
34
+
35
+ def cause_message
36
+ if cause
37
+ reflect_on(cause, :original_message) || reflect_on(cause, :message)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def reflect_on(cause, key)
44
+ logged = cause.respond_to?(:logged) && cause.logged
45
+ cause.respond_to?(key) && logged != true ? cause.public_send(key) : nil
46
+ end
47
+
48
+ def quiet_log
49
+ Steroids::Logger.print(
50
+ "#{Rainbow("▶").magenta} #{Rainbow(self.class.name).red} -- #{Rainbow(self.message).magenta} (quiet)",
51
+ verbosity: :concise,
52
+ format: :raw
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,70 @@
1
+ module Steroids
2
+ module Errors
3
+ module Context
4
+ extend ActiveSupport::Concern
5
+
6
+ included do |base|
7
+ private
8
+
9
+ def define_instance_variables_for(
10
+ message_string,
11
+ status: false,
12
+ message: false,
13
+ errors: nil,
14
+ code: nil,
15
+ cause: nil,
16
+ context: false,
17
+ log: false,
18
+ **splat
19
+ )
20
+ @timestamp = DateTime.now
21
+ @id = SecureRandom.uuid
22
+ @message = assert_message(cause, message_string || message)
23
+ @context = assert_context(cause, context)
24
+ @errors = assert_errors(cause, errors)
25
+ @status = assert_status(cause, status)
26
+ @code = assert_code(code)
27
+ @record = assert_record(cause)
28
+ @quote = quote
29
+ @cause = cause
30
+ end
31
+
32
+ # ------------------------------------------------------------------------------------------
33
+ # DERIVE ERROR ATTRIBUTES
34
+ # ------------------------------------------------------------------------------------------
35
+
36
+ def assert_message(cause, message)
37
+ message || self.default_message
38
+ end
39
+
40
+ def assert_context(cause, context)
41
+ context || reflect_on(cause, :context)
42
+ end
43
+
44
+ def assert_status(cause, status)
45
+ status || reflect_on(cause, :status) || assert_status_from_error(cause) || self.default_status || :unknown_error
46
+ end
47
+
48
+ def assert_status_from_error(cause)
49
+ error_class = cause.is_a?(Exception) ? cause.class : self.class
50
+ ActionDispatch::ExceptionWrapper.rescue_responses[error_class.name] || :internal_server_error
51
+ end
52
+
53
+ def assert_code(status)
54
+ status ? Rack::Utils.status_code(status) : 520
55
+ end
56
+
57
+ def assert_errors(cause, errors = [])
58
+ cause_errors = reflect_on(cause, :errors) || []
59
+ record_instance = reflect_on(cause, :record)
60
+ validations_errors = Array(reflect_on(record_instance, :errors)) || []
61
+ [Array(errors), cause_errors, validations_errors].flatten.compact.uniq
62
+ end
63
+
64
+ def assert_record(cause, errors = [])
65
+ reflect_on(cause, :record)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,29 @@
1
+ module Steroids
2
+ module Errors
3
+ module Quotes
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ QUOTES_FILEPATH = "lib/resources/quotes.yml"
8
+
9
+ protected
10
+
11
+ def load_quotes
12
+ File.join(Steroids.root_path, QUOTES_FILEPATH)
13
+ end
14
+
15
+ def quote
16
+ Rails.cache.fetch("steroids/quotes") do
17
+ begin
18
+ YAML.load_file(path)
19
+ rescue StandardError => e
20
+ Rails.logger.error(e)
21
+ quotes = ["One little bug..."]
22
+ end
23
+ quotes.sample
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+ module Steroids
3
+ module Errors
4
+ # ##############################################################################################
5
+ # Steroids errors
6
+ # ##############################################################################################
7
+
8
+ class GenericError < Steroids::Errors::Base
9
+ self.default_message = "Steroids error (Generic)"
10
+ self.default_status = :generic_error
11
+ end
12
+
13
+ # ##############################################################################################
14
+ # HTTP Error Codes (API)
15
+ # ##############################################################################################
16
+
17
+ # ----------------------------------------------------------------------------------------------
18
+ # BadRequestError
19
+ # ----------------------------------------------------------------------------------------------
20
+
21
+ class BadRequestError < Steroids::Errors::Base
22
+ self.default_message = "Request failed (BadRequestError)."
23
+ self.default_status = :bad_request
24
+ end
25
+
26
+ # ----------------------------------------------------------------------------------------------
27
+ # ConflictError
28
+ # ----------------------------------------------------------------------------------------------
29
+
30
+ class ConflictError < Steroids::Errors::Base
31
+ self.default_message = "Already exists (InternalConflictError)"
32
+ self.default_status = :conflict
33
+ end
34
+
35
+ # ----------------------------------------------------------------------------------------------
36
+ # ForbiddenError
37
+ # ----------------------------------------------------------------------------------------------
38
+
39
+ class ForbiddenError < Steroids::Errors::Base
40
+ self.default_message = "You shall not pass! (ForbiddenError)"
41
+ self.default_status = :forbidden
42
+ end
43
+
44
+ # ----------------------------------------------------------------------------------------------
45
+ # InternalServerError
46
+ # ----------------------------------------------------------------------------------------------
47
+
48
+ class InternalServerError < Steroids::Errors::Base
49
+ self.default_message = "Oops, something went wrong (InternalServerError)"
50
+ self.default_status = :internal_server_error
51
+ end
52
+
53
+ # ----------------------------------------------------------------------------------------------
54
+ # NotFoundError
55
+ # ----------------------------------------------------------------------------------------------
56
+
57
+ class NotFoundError < Steroids::Errors::Base
58
+ self.default_message = "We couldn't find what you were looking for (NotfoundError)"
59
+ self.default_status = :not_found
60
+ end
61
+
62
+ # ----------------------------------------------------------------------------------------------
63
+ # NotImplementedError
64
+ # ----------------------------------------------------------------------------------------------
65
+
66
+ class NotImplementedError < Steroids::Errors::Base
67
+ self.default_message = "This feature hasn't been implemented yet (NotImplementedError)"
68
+ self.default_status = :not_implemented
69
+ end
70
+
71
+ # ----------------------------------------------------------------------------------------------
72
+ # UnauthorizedError
73
+ # ----------------------------------------------------------------------------------------------
74
+
75
+ class UnauthorizedError < Steroids::Errors::Base
76
+ self.default_message = "You shall not pass! (Unauthorized)"
77
+ self.default_status = :unauthorized
78
+ end
79
+
80
+ # ----------------------------------------------------------------------------------------------
81
+ # UnprocessableEntityError
82
+ # ----------------------------------------------------------------------------------------------
83
+
84
+ class UnprocessableEntityError < Steroids::Errors::Base
85
+ self.default_message = "We couldn't understand your request (UnprocessableEntityError)"
86
+ self.default_status = :unprocessable_entity
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,25 @@
1
+ module Steroids
2
+ module Extensions
3
+ module ArrayExtension
4
+ class ElementNotFound < StandardError; end
5
+
6
+ def cast(value)
7
+ self.find { |item| item == value } or raise ElementNotFound.new("Cast: Element not found (#{value})")
8
+ end
9
+
10
+ def find_map(&block)
11
+ return enum_for(:find_map) unless block_given?
12
+
13
+ each do |element|
14
+ result = yield(element)
15
+
16
+ return result if result
17
+ end
18
+
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ Array.include(Steroids::Extensions::ArrayExtension)