cuprum-rails 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +145 -0
- data/DEVELOPMENT.md +20 -0
- data/README.md +356 -63
- data/lib/cuprum/rails/action.rb +32 -16
- data/lib/cuprum/rails/actions/create.rb +62 -15
- data/lib/cuprum/rails/actions/destroy.rb +23 -7
- data/lib/cuprum/rails/actions/edit.rb +23 -7
- data/lib/cuprum/rails/actions/index.rb +30 -10
- data/lib/cuprum/rails/actions/middleware/associations/cache.rb +112 -0
- data/lib/cuprum/rails/actions/middleware/associations/find.rb +23 -0
- data/lib/cuprum/rails/actions/middleware/associations/parent.rb +70 -0
- data/lib/cuprum/rails/actions/middleware/associations/query.rb +140 -0
- data/lib/cuprum/rails/actions/middleware/associations.rb +12 -0
- data/lib/cuprum/rails/actions/middleware/log_request.rb +126 -0
- data/lib/cuprum/rails/actions/middleware/log_result.rb +51 -0
- data/lib/cuprum/rails/actions/middleware/resources/find.rb +44 -0
- data/lib/cuprum/rails/actions/middleware/resources/query.rb +91 -0
- data/lib/cuprum/rails/actions/middleware/resources.rb +11 -0
- data/lib/cuprum/rails/actions/middleware.rb +13 -0
- data/lib/cuprum/rails/actions/new.rb +16 -4
- data/lib/cuprum/rails/actions/parameter_validation.rb +60 -0
- data/lib/cuprum/rails/actions/resource_action.rb +119 -42
- data/lib/cuprum/rails/actions/show.rb +23 -7
- data/lib/cuprum/rails/actions/update.rb +70 -22
- data/lib/cuprum/rails/actions.rb +11 -7
- data/lib/cuprum/rails/collection.rb +27 -47
- data/lib/cuprum/rails/command.rb +3 -1
- data/lib/cuprum/rails/commands/destroy_one.rb +10 -6
- data/lib/cuprum/rails/commands/find_many.rb +8 -1
- data/lib/cuprum/rails/commands/find_matching.rb +1 -1
- data/lib/cuprum/rails/commands/find_one.rb +8 -0
- data/lib/cuprum/rails/commands/insert_one.rb +17 -6
- data/lib/cuprum/rails/commands/update_one.rb +16 -5
- data/lib/cuprum/rails/constraints/parameters_contract.rb +14 -0
- data/lib/cuprum/rails/constraints.rb +10 -0
- data/lib/cuprum/rails/controller.rb +12 -2
- data/lib/cuprum/rails/controllers/action.rb +100 -0
- data/lib/cuprum/rails/controllers/class_methods/actions.rb +33 -7
- data/lib/cuprum/rails/controllers/class_methods/configuration.rb +36 -0
- data/lib/cuprum/rails/controllers/class_methods/middleware.rb +88 -0
- data/lib/cuprum/rails/controllers/class_methods/validations.rb +2 -2
- data/lib/cuprum/rails/controllers/configuration.rb +41 -1
- data/lib/cuprum/rails/controllers/middleware.rb +59 -0
- data/lib/cuprum/rails/controllers.rb +2 -0
- data/lib/cuprum/rails/errors/invalid_parameters.rb +55 -0
- data/lib/cuprum/rails/errors/invalid_statement.rb +11 -0
- data/lib/cuprum/rails/errors/missing_parameter.rb +42 -0
- data/lib/cuprum/rails/errors/resource_error.rb +46 -0
- data/lib/cuprum/rails/errors.rb +6 -1
- data/lib/cuprum/rails/map_errors.rb +29 -1
- data/lib/cuprum/rails/query.rb +1 -1
- data/lib/cuprum/rails/repository.rb +12 -25
- data/lib/cuprum/rails/request.rb +149 -60
- data/lib/cuprum/rails/resource.rb +119 -85
- data/lib/cuprum/rails/responders/base_responder.rb +78 -0
- data/lib/cuprum/rails/responders/html/plural_resource.rb +9 -39
- data/lib/cuprum/rails/responders/html/rendering.rb +81 -0
- data/lib/cuprum/rails/responders/html/resource.rb +107 -0
- data/lib/cuprum/rails/responders/html/singular_resource.rb +9 -38
- data/lib/cuprum/rails/responders/html.rb +2 -0
- data/lib/cuprum/rails/responders/html_responder.rb +8 -52
- data/lib/cuprum/rails/responders/json/resource.rb +3 -3
- data/lib/cuprum/rails/responders/json_responder.rb +31 -16
- data/lib/cuprum/rails/responders/matching.rb +29 -27
- data/lib/cuprum/rails/responders/serialization.rb +11 -9
- data/lib/cuprum/rails/responders.rb +1 -0
- data/lib/cuprum/rails/responses/head_response.rb +24 -0
- data/lib/cuprum/rails/responses/html/redirect_back_response.rb +55 -0
- data/lib/cuprum/rails/responses/html/redirect_response.rb +19 -4
- data/lib/cuprum/rails/responses/html/render_response.rb +17 -5
- data/lib/cuprum/rails/responses/html.rb +6 -2
- data/lib/cuprum/rails/responses.rb +1 -0
- data/lib/cuprum/rails/result.rb +36 -0
- data/lib/cuprum/rails/routes.rb +36 -23
- data/lib/cuprum/rails/rspec/contract_helpers.rb +57 -0
- data/lib/cuprum/rails/rspec/contracts/action_contracts.rb +754 -0
- data/lib/cuprum/rails/rspec/contracts/actions/create_contracts.rb +289 -0
- data/lib/cuprum/rails/rspec/contracts/actions/destroy_contracts.rb +164 -0
- data/lib/cuprum/rails/rspec/contracts/actions/edit_contracts.rb +73 -0
- data/lib/cuprum/rails/rspec/contracts/actions/index_contracts.rb +108 -0
- data/lib/cuprum/rails/rspec/contracts/actions/new_contracts.rb +111 -0
- data/lib/cuprum/rails/rspec/contracts/actions/show_contracts.rb +72 -0
- data/lib/cuprum/rails/rspec/contracts/actions/update_contracts.rb +263 -0
- data/lib/cuprum/rails/rspec/contracts/actions.rb +8 -0
- data/lib/cuprum/rails/rspec/contracts/command_contracts.rb +479 -0
- data/lib/cuprum/rails/rspec/contracts/responder_contracts.rb +232 -0
- data/lib/cuprum/rails/rspec/contracts/routes_contracts.rb +363 -0
- data/lib/cuprum/rails/rspec/contracts/serializers_contracts.rb +70 -0
- data/lib/cuprum/rails/rspec/contracts.rb +8 -0
- data/lib/cuprum/rails/rspec/matchers/be_a_result_matcher.rb +64 -0
- data/lib/cuprum/rails/rspec/matchers.rb +41 -0
- data/lib/cuprum/rails/serializers/base_serializer.rb +60 -0
- data/lib/cuprum/rails/serializers/context.rb +84 -0
- data/lib/cuprum/rails/serializers/json/active_record_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/array_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/attributes_serializer.rb +95 -172
- data/lib/cuprum/rails/serializers/json/error_serializer.rb +2 -2
- data/lib/cuprum/rails/serializers/json/hash_serializer.rb +9 -8
- data/lib/cuprum/rails/serializers/json/identity_serializer.rb +3 -3
- data/lib/cuprum/rails/serializers/json/properties_serializer.rb +252 -0
- data/lib/cuprum/rails/serializers/json.rb +2 -1
- data/lib/cuprum/rails/serializers.rb +3 -1
- data/lib/cuprum/rails/version.rb +1 -1
- data/lib/cuprum/rails.rb +19 -16
- metadata +73 -131
- data/lib/cuprum/rails/controller_action.rb +0 -121
- data/lib/cuprum/rails/errors/missing_parameters.rb +0 -33
- data/lib/cuprum/rails/errors/missing_primary_key.rb +0 -46
- data/lib/cuprum/rails/errors/undefined_permitted_attributes.rb +0 -34
- data/lib/cuprum/rails/rspec/command_contract.rb +0 -460
- data/lib/cuprum/rails/rspec/define_route_contract.rb +0 -84
- data/lib/cuprum/rails/serializers/json/serializer.rb +0 -66
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'cuprum/rails/
|
3
|
+
require 'cuprum/rails/controllers/action'
|
4
4
|
require 'cuprum/rails/controllers/class_methods'
|
5
5
|
|
6
6
|
module Cuprum::Rails::Controllers::ClassMethods
|
@@ -18,8 +18,7 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
18
18
|
validate_class(action_class, as: 'action class')
|
19
19
|
|
20
20
|
action_name = action_name.intern
|
21
|
-
own_actions[action_name] = Cuprum::Rails::
|
22
|
-
configuration,
|
21
|
+
own_actions[action_name] = Cuprum::Rails::Controllers::Action.new(
|
23
22
|
action_class: action_class,
|
24
23
|
action_name: action_name,
|
25
24
|
member_action: member
|
@@ -28,7 +27,7 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
28
27
|
define_action(action_name)
|
29
28
|
end
|
30
29
|
|
31
|
-
# @return [Hash<Symbol, Cuprum::Rails::
|
30
|
+
# @return [Hash<Symbol, Cuprum::Rails::Controllers::Action>] the actions
|
32
31
|
# defined for the controller.
|
33
32
|
def actions
|
34
33
|
ancestors
|
@@ -38,18 +37,45 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
38
37
|
.reduce(&:merge)
|
39
38
|
end
|
40
39
|
|
40
|
+
# @private
|
41
|
+
def apply_request_defaults(request)
|
42
|
+
request.format ||= configuration.default_format
|
43
|
+
end
|
44
|
+
|
45
|
+
# Generates a Cuprum::Rails::Request from a native request.
|
46
|
+
#
|
47
|
+
# Override this method to generate a request subclass.
|
48
|
+
#
|
49
|
+
# @param context [#request] the controller or controller context.
|
50
|
+
# @param options [Hash{Symbol=>Object}] additional options for the request.
|
51
|
+
#
|
52
|
+
# @return [Cuprum::Rails::Request] the generated request.
|
53
|
+
def build_request(context, **options)
|
54
|
+
Cuprum::Rails::Request.build(
|
55
|
+
context: context,
|
56
|
+
request: context.request,
|
57
|
+
**options
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
41
61
|
# @private
|
42
62
|
def own_actions
|
63
|
+
# :nocov:
|
43
64
|
@own_actions ||= {}
|
65
|
+
# :nocov:
|
44
66
|
end
|
45
67
|
|
46
68
|
private
|
47
69
|
|
48
70
|
def define_action(action_name)
|
49
71
|
define_method(action_name) do
|
50
|
-
|
51
|
-
|
52
|
-
|
72
|
+
action = self.class.actions[action_name]
|
73
|
+
request =
|
74
|
+
self
|
75
|
+
.class
|
76
|
+
.build_request(self, member_action: action.member_action?)
|
77
|
+
.tap { |req| self.class.apply_request_defaults(req) }
|
78
|
+
response = action.call(self, request)
|
53
79
|
response.call(self)
|
54
80
|
end
|
55
81
|
end
|
@@ -13,11 +13,40 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
13
13
|
Cuprum::Rails::Controllers::Configuration.new(self)
|
14
14
|
end
|
15
15
|
|
16
|
+
# @overload default_format
|
17
|
+
# @return [Symbol] the default format for controller requests.
|
18
|
+
#
|
19
|
+
# @overload default_format(format)
|
20
|
+
# Sets the default format for controller requests.
|
21
|
+
#
|
22
|
+
# @param format [String, Symbol] The format to set as default.
|
23
|
+
def default_format(format = nil)
|
24
|
+
if format.nil?
|
25
|
+
return @default_format if @default_format
|
26
|
+
|
27
|
+
return superclass.default_format if controller_class?(superclass)
|
28
|
+
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
validate_name(format, as: 'format')
|
33
|
+
|
34
|
+
@default_format = format.intern
|
35
|
+
end
|
36
|
+
|
16
37
|
# @private
|
17
38
|
def own_responders
|
18
39
|
@own_responders ||= {}
|
19
40
|
end
|
20
41
|
|
42
|
+
# Returns the repository defined for the controller.
|
43
|
+
#
|
44
|
+
# @return [Cuprum::Collections::Repository] the repository containing the
|
45
|
+
# data collections for the application or scope.
|
46
|
+
def repository
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
21
50
|
# Returns the resource defined for the controller.
|
22
51
|
#
|
23
52
|
# Controller subclasses must override this method.
|
@@ -60,5 +89,12 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
60
89
|
json: Cuprum::Rails::Serializers::Json.default_serializers
|
61
90
|
}
|
62
91
|
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def controller_class?(other)
|
96
|
+
other.singleton_class <
|
97
|
+
Cuprum::Rails::Controllers::ClassMethods::Configuration
|
98
|
+
end
|
63
99
|
end
|
64
100
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/controllers/class_methods'
|
4
|
+
require 'cuprum/rails/controllers/middleware'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Controllers::ClassMethods
|
7
|
+
# Provides a DSL for defining controller middleware.
|
8
|
+
module Middleware
|
9
|
+
# @overload middleware
|
10
|
+
# @return [Array<Cuprum::Rails::Controllers::Middleware>] the configured
|
11
|
+
# middleware for the controller.
|
12
|
+
#
|
13
|
+
# @overload middleware(command, except: [], only: {]})
|
14
|
+
# Defines middleware for the controller.
|
15
|
+
#
|
16
|
+
# @param command [Class, Cuprum::Command] The middleware command.
|
17
|
+
# Middleware commands must take two parameters: a next_command argument,
|
18
|
+
# and a request: keyword.
|
19
|
+
# @param except [Array<String, Symbol>] Action names to exclude. The
|
20
|
+
# middleware will not be applied to actions on this list.
|
21
|
+
# @param only [Array<String, Symbol>] Action names to include If this is
|
22
|
+
# not empty, the middleware will only be applied to actions on this
|
23
|
+
# list.
|
24
|
+
#
|
25
|
+
# @see Cuprum::Middleware
|
26
|
+
def middleware(command = nil, except: [], only: [])
|
27
|
+
unless command.nil?
|
28
|
+
own_middleware <<
|
29
|
+
build_middleware(command: command, except: except, only: only)
|
30
|
+
end
|
31
|
+
|
32
|
+
ancestors
|
33
|
+
.select { |ancestor| ancestor.respond_to?(:own_middleware) }
|
34
|
+
.reverse_each
|
35
|
+
.map(&:own_middleware)
|
36
|
+
.reduce(&:+)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @private
|
40
|
+
def own_middleware
|
41
|
+
@own_middleware ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def build_middleware(command:, except:, only:)
|
47
|
+
validate_command!(command)
|
48
|
+
validate_action_names!(except, as: 'except')
|
49
|
+
validate_action_names!(only, as: 'only')
|
50
|
+
|
51
|
+
Cuprum::Rails::Controllers::Middleware.new(
|
52
|
+
command: command,
|
53
|
+
except: except,
|
54
|
+
only: only
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid_action_names?(action_names)
|
59
|
+
return false unless action_names.is_a?(Array)
|
60
|
+
|
61
|
+
action_names.all? do |action_name|
|
62
|
+
next false unless action_name.is_a?(String) || action_name.is_a?(Symbol)
|
63
|
+
|
64
|
+
!action_name.empty?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_action_names!(action_names, as:)
|
69
|
+
return if action_names.nil?
|
70
|
+
|
71
|
+
return if valid_action_names?(action_names)
|
72
|
+
|
73
|
+
raise ArgumentError,
|
74
|
+
"#{as} must be a list of action names",
|
75
|
+
caller(1..-1)
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_command!(command)
|
79
|
+
return if command.is_a?(Cuprum::Command)
|
80
|
+
|
81
|
+
return if command.is_a?(Class) && command < Cuprum::Command
|
82
|
+
|
83
|
+
raise ArgumentError,
|
84
|
+
'command must be an instance of or subclass of Cuprum::Command',
|
85
|
+
caller(1..-1)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -7,13 +7,13 @@ module Cuprum::Rails::Controllers::ClassMethods
|
|
7
7
|
module Validations
|
8
8
|
private
|
9
9
|
|
10
|
-
def validate_class(value, as:)
|
10
|
+
def validate_class(value, as:)
|
11
11
|
return if value.is_a?(Class)
|
12
12
|
|
13
13
|
raise ArgumentError, "#{as} must be a Class", caller(1..-1)
|
14
14
|
end
|
15
15
|
|
16
|
-
def validate_name(value, as:)
|
16
|
+
def validate_name(value, as:)
|
17
17
|
raise ArgumentError, "#{as} can't be blank", caller(1..-1) if value.nil?
|
18
18
|
|
19
19
|
unless value.is_a?(String) || value.is_a?(Symbol)
|
@@ -18,6 +18,20 @@ module Cuprum::Rails::Controllers
|
|
18
18
|
# @return [#resource, #responders] the controller to delegate configuration.
|
19
19
|
attr_reader :controller
|
20
20
|
|
21
|
+
# @!method controller_name
|
22
|
+
# @return [String] the name of the controller.
|
23
|
+
|
24
|
+
# @!method default_format
|
25
|
+
# @return [Symbol] the default format for controller requests.
|
26
|
+
|
27
|
+
# @!method middleware
|
28
|
+
# @return [Array<Cuprum::Rails::Controllers::Middleware>] the middleware
|
29
|
+
# defined for the controller.
|
30
|
+
|
31
|
+
# @!method repository
|
32
|
+
# @return [Cuprum::Collections::Repository] the repository containing the
|
33
|
+
# data collections for the application or scope.
|
34
|
+
|
21
35
|
# @!method resource
|
22
36
|
# @return [Cuprum::Rails::Resource] the resource defined for the
|
23
37
|
# controller.
|
@@ -31,13 +45,27 @@ module Cuprum::Rails::Controllers
|
|
31
45
|
# serializers for converting result values into serialized data.
|
32
46
|
|
33
47
|
def_delegators :@controller,
|
48
|
+
:controller_name,
|
49
|
+
:default_format,
|
50
|
+
:middleware,
|
51
|
+
:repository,
|
34
52
|
:resource,
|
35
53
|
:responders,
|
36
54
|
:serializers
|
37
55
|
|
56
|
+
# Finds the configured middleware for the requested action name.
|
57
|
+
#
|
58
|
+
# @param action_name [Symbol] The name of the action.
|
59
|
+
#
|
60
|
+
# @return [Array<Cuprum::Rails::Controllers::Middleware>] the configured
|
61
|
+
# middleware for the action.
|
62
|
+
def middleware_for(action_name)
|
63
|
+
middleware.select { |item| item.matches?(action_name) }
|
64
|
+
end
|
65
|
+
|
38
66
|
# Finds the configured responder for the requested format.
|
39
67
|
#
|
40
|
-
# @param format [Symbol]
|
68
|
+
# @param format [Symbol] the format to respond to.
|
41
69
|
#
|
42
70
|
# @return [Class] the responder class defined for the format.
|
43
71
|
#
|
@@ -49,5 +77,17 @@ module Cuprum::Rails::Controllers
|
|
49
77
|
"no responder registered for format #{format.inspect}"
|
50
78
|
end
|
51
79
|
end
|
80
|
+
|
81
|
+
# Finds the configured serializers for the requested format.
|
82
|
+
#
|
83
|
+
# @param format [Symbol] the format to respond to.
|
84
|
+
#
|
85
|
+
# @return [Hash<Class, Object>] the serializers for converting result values
|
86
|
+
# into serialized data.
|
87
|
+
def serializers_for(format)
|
88
|
+
serializers
|
89
|
+
.select { |key, _| key.is_a?(Class) }
|
90
|
+
.merge(serializers.fetch(format, {}))
|
91
|
+
end
|
52
92
|
end
|
53
93
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require 'cuprum/rails/controllers'
|
6
|
+
|
7
|
+
module Cuprum::Rails::Controllers
|
8
|
+
# A configured middleware option for a controller.
|
9
|
+
class Middleware
|
10
|
+
# @param command [Cuprum::Command] The middleware command to wrap the
|
11
|
+
# action or actions.
|
12
|
+
# @param except [Array<Symbol>] A list of action names; the middleware will
|
13
|
+
# not be applied to actions on the list.
|
14
|
+
# @param only [Array<Symbol>] A list of action names; the middleware will
|
15
|
+
# be applied only to actions on the list.
|
16
|
+
def initialize(command:, except: [], only: [])
|
17
|
+
@command = command
|
18
|
+
@except = Set.new(except.map(&:intern))
|
19
|
+
@only = Set.new(only.map(&:intern))
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Cuprum::Middleware] the middleware command to wrap the action or
|
23
|
+
# actions.
|
24
|
+
attr_reader :command
|
25
|
+
|
26
|
+
# @return [Array<Symbol>] a list of action names; the middleware will not be
|
27
|
+
# applied to actions on the list.
|
28
|
+
attr_reader :except
|
29
|
+
|
30
|
+
# @return [Array<Symbol>] a list of action names; the middleware will be
|
31
|
+
# applied only to actions on the list.
|
32
|
+
attr_reader :only
|
33
|
+
|
34
|
+
# @private
|
35
|
+
def ==(other)
|
36
|
+
other.is_a?(Cuprum::Rails::Controllers::Middleware) &&
|
37
|
+
other.command == command &&
|
38
|
+
other.except == except &&
|
39
|
+
other.only == only
|
40
|
+
end
|
41
|
+
|
42
|
+
# Checks if the middleware will be applied to the named action.
|
43
|
+
#
|
44
|
+
# If the middleware defines any :except actions, returns false if the action
|
45
|
+
# name is in the set. If the middleware defines any :only actions, returns
|
46
|
+
# false unless the action name is in the set. Otherwise, returns true.
|
47
|
+
#
|
48
|
+
# @param action_name [Symbol] The name of the action.
|
49
|
+
#
|
50
|
+
# @return [true, false] whether the middleware will be applied.
|
51
|
+
def matches?(action_name)
|
52
|
+
return false unless except.empty? || except.exclude?(action_name)
|
53
|
+
return false unless only.empty? || only.include?(action_name)
|
54
|
+
|
55
|
+
true
|
56
|
+
end
|
57
|
+
alias match? matches?
|
58
|
+
end
|
59
|
+
end
|
@@ -5,6 +5,8 @@ require 'cuprum/rails'
|
|
5
5
|
module Cuprum::Rails
|
6
6
|
# Namespace for controller-specific functionality.
|
7
7
|
module Controllers
|
8
|
+
autoload :Action, 'cuprum/rails/controllers/action'
|
8
9
|
autoload :Configuration, 'cuprum/rails/controllers/configuration'
|
10
|
+
autoload :Middleware, 'cuprum/rails/controllers/middleware'
|
9
11
|
end
|
10
12
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/error'
|
4
|
+
|
5
|
+
require 'cuprum/rails/errors'
|
6
|
+
|
7
|
+
module Cuprum::Rails::Errors
|
8
|
+
# Error class when a parameters hash does not match the expected contract.
|
9
|
+
class InvalidParameters < Cuprum::Error
|
10
|
+
# Short string used to identify the type of error.
|
11
|
+
TYPE = 'cuprum.rails.errors.invalid_parameters'
|
12
|
+
|
13
|
+
# @param errors [Stannum::Errors] the errors returned by the contract.
|
14
|
+
def initialize(errors:)
|
15
|
+
@errors = errors
|
16
|
+
|
17
|
+
super(message: default_message, errors: errors)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Stannum::Errors] the errors returned by the contract.
|
21
|
+
attr_reader :errors
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def as_json_data
|
26
|
+
error_data =
|
27
|
+
errors
|
28
|
+
.group_by_path
|
29
|
+
.to_h do |path, errors|
|
30
|
+
[
|
31
|
+
join_path(path),
|
32
|
+
errors.map { |error| format_error(error) }
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
{ 'errors' => error_data }
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_message
|
40
|
+
"invalid request parameters - #{errors.summary}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def format_error(error)
|
44
|
+
tools.hash_tools.convert_keys_to_strings(error)
|
45
|
+
end
|
46
|
+
|
47
|
+
def join_path(path)
|
48
|
+
path.join('.')
|
49
|
+
end
|
50
|
+
|
51
|
+
def tools
|
52
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/errors'
|
4
|
+
|
5
|
+
module Cuprum::Rails::Errors
|
6
|
+
# Error class when a database execution error occurs.
|
7
|
+
class InvalidStatement < Cuprum::Error
|
8
|
+
# Short string used to identify the type of error.
|
9
|
+
TYPE = 'cuprum.rails.errors.invalid_statement'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/errors'
|
4
|
+
|
5
|
+
module Cuprum::Rails::Errors
|
6
|
+
# Error class when a parameters hash does not include the expected keys.
|
7
|
+
class MissingParameter < Cuprum::Error
|
8
|
+
# Short string used to identify the type of error.
|
9
|
+
TYPE = 'cuprum.rails.errors.missing_parameter'
|
10
|
+
|
11
|
+
# @param parameter_name [String, Symbol] the name of the missing parameter.
|
12
|
+
# @param parameters [Hash] the received parameters.
|
13
|
+
def initialize(parameter_name:, parameters:)
|
14
|
+
@parameter_name = parameter_name
|
15
|
+
@parameters = parameters
|
16
|
+
|
17
|
+
super(
|
18
|
+
message: default_message,
|
19
|
+
parameter_name: parameter_name
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [String, Symbol] the name of the missing parameter.
|
24
|
+
attr_reader :parameter_name
|
25
|
+
|
26
|
+
# @return [Hash] the received parameters.
|
27
|
+
attr_reader :parameters
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def as_json_data
|
32
|
+
{
|
33
|
+
'parameter_name' => parameter_name,
|
34
|
+
'parameters' => parameters
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_message
|
39
|
+
"missing parameter #{parameter_name.inspect}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/error'
|
4
|
+
|
5
|
+
require 'cuprum/rails/errors'
|
6
|
+
|
7
|
+
module Cuprum::Rails::Errors
|
8
|
+
# Error class when a resource is not correctly configured for an action.
|
9
|
+
class ResourceError < Cuprum::Error
|
10
|
+
# Short string used to identify the type of error.
|
11
|
+
TYPE = 'cuprum.rails.errors.resource_error'
|
12
|
+
|
13
|
+
# @param resource [Cuprum::Rails::Resource] the errored resource.
|
14
|
+
# @param message [String] the message to display, if any.
|
15
|
+
def initialize(resource:, message: nil)
|
16
|
+
@resource = resource
|
17
|
+
|
18
|
+
super(message: generate_message(message), resource: resource)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Cuprum::Rails::Resource] the errored resource.
|
22
|
+
attr_reader :resource
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def as_json_data
|
27
|
+
{
|
28
|
+
'resource' => {
|
29
|
+
'entity_class' => resource.entity_class.to_s,
|
30
|
+
'name' => resource.name.to_s,
|
31
|
+
'qualified_name' => resource.qualified_name.to_s,
|
32
|
+
'singular' => resource.singular?,
|
33
|
+
'singular_name' => resource.singular_name.to_s
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate_message(message = nil)
|
39
|
+
prefix = "invalid resource #{resource.name}"
|
40
|
+
|
41
|
+
return prefix if message.blank?
|
42
|
+
|
43
|
+
"#{prefix} - #{message}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cuprum/rails/errors.rb
CHANGED
@@ -4,5 +4,10 @@ require 'cuprum/rails'
|
|
4
4
|
|
5
5
|
module Cuprum::Rails
|
6
6
|
# Namespace for custom Cuprum::Rails error classes.
|
7
|
-
module Errors
|
7
|
+
module Errors
|
8
|
+
autoload :InvalidParameters, 'cuprum/rails/errors/invalid_parameters'
|
9
|
+
autoload :InvalidStatement, 'cuprum/rails/errors/invalid_statement'
|
10
|
+
autoload :MissingParameter, 'cuprum/rails/errors/missing_parameter'
|
11
|
+
autoload :ResourceError, 'cuprum/rails/errors/resource_error'
|
12
|
+
end
|
8
13
|
end
|
@@ -28,17 +28,45 @@ module Cuprum::Rails
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
+
# :nocov:
|
31
32
|
def map_errors(native_errors:)
|
33
|
+
if Rails.version < '6.1'
|
34
|
+
map_errors_hash(native_errors: native_errors)
|
35
|
+
else
|
36
|
+
map_errors_object(native_errors: native_errors)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def map_errors_hash(native_errors:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
41
|
+
errors = Stannum::Errors.new
|
42
|
+
details = native_errors.details
|
43
|
+
messages = native_errors.messages
|
44
|
+
|
45
|
+
native_errors.keys.each do |attribute| # rubocop:disable Style/HashEachMethods
|
46
|
+
scoped = attribute == :base ? errors : errors[attribute]
|
47
|
+
|
48
|
+
details[attribute].each.with_index do |hsh, index|
|
49
|
+
message = messages[attribute][index]
|
50
|
+
|
51
|
+
scoped.add(hsh[:error], **hsh.except(:error).merge(message: message))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
errors
|
56
|
+
end
|
57
|
+
|
58
|
+
def map_errors_object(native_errors:)
|
32
59
|
errors = Stannum::Errors.new
|
33
60
|
|
34
61
|
native_errors.each do |error|
|
35
62
|
attribute = error.attribute
|
36
63
|
scoped = attribute == :base ? errors : errors[attribute]
|
37
64
|
|
38
|
-
scoped.add(error.type, message: error.message
|
65
|
+
scoped.add(error.type, **error.options.merge(message: error.message))
|
39
66
|
end
|
40
67
|
|
41
68
|
errors
|
42
69
|
end
|
43
70
|
end
|
71
|
+
# :nocov:
|
44
72
|
end
|
data/lib/cuprum/rails/query.rb
CHANGED
@@ -24,7 +24,7 @@ module Cuprum::Rails
|
|
24
24
|
super()
|
25
25
|
|
26
26
|
default_order = { record_class.primary_key => :asc }
|
27
|
-
@native_query = native_query || record_class.
|
27
|
+
@native_query = native_query || record_class.order(default_order)
|
28
28
|
@record_class = record_class
|
29
29
|
@limit = nil
|
30
30
|
@offset = nil
|
@@ -8,37 +8,24 @@ require 'cuprum/rails/collection'
|
|
8
8
|
module Cuprum::Rails
|
9
9
|
# A repository represents a group of Rails collections.
|
10
10
|
class Repository < Cuprum::Collections::Repository
|
11
|
-
|
12
|
-
#
|
13
|
-
# @param record_class [Class] The ActiveRecord class for the collection.
|
14
|
-
# @param options [Hash] Additional options to pass to Collection.new
|
15
|
-
#
|
16
|
-
# @return [Cuprum::Rails::Collection] the created collection.
|
17
|
-
#
|
18
|
-
# @see Cuprum::Rails::Collection#initialize.
|
19
|
-
def build(record_class:, **options)
|
20
|
-
validate_record_class!(record_class)
|
21
|
-
|
22
|
-
collection = Cuprum::Rails::Collection.new(
|
23
|
-
record_class: record_class,
|
24
|
-
**options
|
25
|
-
)
|
26
|
-
|
27
|
-
add(collection)
|
11
|
+
private
|
28
12
|
|
29
|
-
|
13
|
+
def build_collection(**options)
|
14
|
+
Cuprum::Rails::Collection.new(**options)
|
30
15
|
end
|
31
16
|
|
32
|
-
|
17
|
+
def qualified_name_for(**parameters)
|
18
|
+
Cuprum::Collections::Relation::Disambiguation
|
19
|
+
.resolve_parameters(
|
20
|
+
parameters,
|
21
|
+
entity_class: :record_class,
|
22
|
+
name: :collection_name
|
23
|
+
)
|
24
|
+
.fetch(:qualified_name)
|
25
|
+
end
|
33
26
|
|
34
27
|
def valid_collection?(collection)
|
35
28
|
collection.is_a?(Cuprum::Rails::Collection)
|
36
29
|
end
|
37
|
-
|
38
|
-
def validate_record_class!(record_class)
|
39
|
-
return if record_class.is_a?(Class) && record_class < ActiveRecord::Base
|
40
|
-
|
41
|
-
raise ArgumentError, 'record class must be an ActiveRecord model'
|
42
|
-
end
|
43
30
|
end
|
44
31
|
end
|