cuprum-rails 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -5,13 +5,18 @@ require 'cuprum/rails/responses/html'
|
|
5
5
|
module Cuprum::Rails::Responses::Html
|
6
6
|
# Encapsulates an HTML response that redirects to a given path.
|
7
7
|
class RedirectResponse
|
8
|
-
# @param
|
9
|
-
# @param
|
10
|
-
|
8
|
+
# @param flash [Hash] the flash messages to set.
|
9
|
+
# @param path [String] the path or url to redirect to.
|
10
|
+
# @param status [Integer] the HTTP status of the response.
|
11
|
+
def initialize(path, flash: {}, status: 302)
|
12
|
+
@flash = flash
|
11
13
|
@path = path
|
12
14
|
@status = status
|
13
15
|
end
|
14
16
|
|
17
|
+
# @return [Hash] the flash messages to set.
|
18
|
+
attr_reader :flash
|
19
|
+
|
15
20
|
# @return [String] the path or url to redirect to.
|
16
21
|
attr_reader :path
|
17
22
|
|
@@ -20,10 +25,20 @@ module Cuprum::Rails::Responses::Html
|
|
20
25
|
|
21
26
|
# Calls the renderer's #redirect_to method with the path and status.
|
22
27
|
#
|
23
|
-
# @param renderer [#redirect_to] The
|
28
|
+
# @param renderer [#redirect_to] The tontext for executing the response,
|
24
29
|
# such as a Rails controller.
|
25
30
|
def call(renderer)
|
31
|
+
assign_flash(renderer)
|
32
|
+
|
26
33
|
renderer.redirect_to(path, status: status)
|
27
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def assign_flash(renderer)
|
39
|
+
flash.each do |key, value|
|
40
|
+
renderer.flash[key] = value
|
41
|
+
end
|
42
|
+
end
|
28
43
|
end
|
29
44
|
end
|
@@ -5,12 +5,14 @@ require 'cuprum/rails/responses/html'
|
|
5
5
|
module Cuprum::Rails::Responses::Html
|
6
6
|
# Encapsulates an HTML response that renders a given template.
|
7
7
|
class RenderResponse
|
8
|
-
# @param assigns [Hash]
|
9
|
-
# @param
|
10
|
-
# @param
|
11
|
-
# @param
|
12
|
-
|
8
|
+
# @param assigns [Hash] variables to assign when rendering the template.
|
9
|
+
# @param flash [Hash] the flash messages to set.
|
10
|
+
# @param layout [String] the layout to render.
|
11
|
+
# @param status [Integer] the HTTP status of the response.
|
12
|
+
# @param template [String, Symbol] the template to render.
|
13
|
+
def initialize(template, assigns: {}, flash: {}, layout: nil, status: 200)
|
13
14
|
@assigns = assigns
|
15
|
+
@flash = flash
|
14
16
|
@layout = layout
|
15
17
|
@status = status
|
16
18
|
@template = template
|
@@ -19,6 +21,9 @@ module Cuprum::Rails::Responses::Html
|
|
19
21
|
# @return [Hash] variables to assign when rendering the template.
|
20
22
|
attr_reader :assigns
|
21
23
|
|
24
|
+
# @return [Hash] the flash messages to set.
|
25
|
+
attr_reader :flash
|
26
|
+
|
22
27
|
# @return [String] the layout to render.
|
23
28
|
attr_reader :layout
|
24
29
|
|
@@ -33,6 +38,7 @@ module Cuprum::Rails::Responses::Html
|
|
33
38
|
# @param renderer [#render] The context for executing the response, such as
|
34
39
|
# a Rails controller.
|
35
40
|
def call(renderer)
|
41
|
+
assign_flash(renderer)
|
36
42
|
assign_variables(renderer)
|
37
43
|
|
38
44
|
options = { status: status }
|
@@ -43,6 +49,12 @@ module Cuprum::Rails::Responses::Html
|
|
43
49
|
|
44
50
|
private
|
45
51
|
|
52
|
+
def assign_flash(renderer)
|
53
|
+
flash.each do |key, value|
|
54
|
+
renderer.flash.now[key] = value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
46
58
|
def assign_variables(renderer)
|
47
59
|
assigns.each do |key, value|
|
48
60
|
renderer.instance_variable_set("@#{key}", value)
|
@@ -5,7 +5,11 @@ require 'cuprum/rails/responses'
|
|
5
5
|
module Cuprum::Rails::Responses
|
6
6
|
# Namespace for response objects, which encapsulate Html responses.
|
7
7
|
module Html
|
8
|
-
autoload :
|
9
|
-
|
8
|
+
autoload :RedirectBackResponse,
|
9
|
+
'cuprum/rails/responses/html/redirect_back_response'
|
10
|
+
autoload :RedirectResponse,
|
11
|
+
'cuprum/rails/responses/html/redirect_response'
|
12
|
+
autoload :RenderResponse,
|
13
|
+
'cuprum/rails/responses/html/render_response'
|
10
14
|
end
|
11
15
|
end
|
@@ -5,6 +5,7 @@ require 'cuprum/rails'
|
|
5
5
|
module Cuprum::Rails
|
6
6
|
# Namespace for response objects, which encapsulate server responses.
|
7
7
|
module Responses
|
8
|
+
autoload :HeadResponse, 'cuprum/rails/responses/head_response'
|
8
9
|
autoload :Html, 'cuprum/rails/responses/html'
|
9
10
|
autoload :JsonResponse, 'cuprum/rails/responses/json_response'
|
10
11
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails'
|
4
|
+
|
5
|
+
module Cuprum::Rails
|
6
|
+
# Result class representing the result of calling an action.
|
7
|
+
#
|
8
|
+
# In addition to the standard properties inherited from Cuprum::Result, each
|
9
|
+
# Cuprum::Rails::Result also includes a #metadata property. This represents
|
10
|
+
# secondary information about the result that may be relevant for rendering or
|
11
|
+
# displaying the data, but is not part of the requested value. For example.
|
12
|
+
# information about the current controller would be metadata, as would the
|
13
|
+
# current authentication session.
|
14
|
+
class Result < Cuprum::Result
|
15
|
+
# @param value [Object] the value returned by calling the action.
|
16
|
+
# @param error [Cuprum::Error] the error (if any) generated when the action
|
17
|
+
# was called.
|
18
|
+
# @param metadata [Hash{Symbol => Object}] the request or action metadata.
|
19
|
+
# @param status [String, Symbol, nil] the status of the result. Must be
|
20
|
+
# :success, :failure, or nil.
|
21
|
+
def initialize(error: nil, metadata: {}, status: nil, value: nil)
|
22
|
+
super(error: error, status: status, value: value)
|
23
|
+
|
24
|
+
@metadata = metadata
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Hash{Symbol => Object}] the request or action metadata.
|
28
|
+
attr_reader :metadata
|
29
|
+
|
30
|
+
# @return [Hash{Symbol => Object}] a Hash representation of the result.
|
31
|
+
def properties
|
32
|
+
super().merge(metadata: metadata)
|
33
|
+
end
|
34
|
+
alias to_h properties
|
35
|
+
end
|
36
|
+
end
|
data/lib/cuprum/rails/routes.rb
CHANGED
@@ -4,7 +4,7 @@ require 'cuprum/rails'
|
|
4
4
|
|
5
5
|
module Cuprum::Rails
|
6
6
|
# Represent the routes available for a given resource.
|
7
|
-
class Routes
|
7
|
+
class Routes # rubocop:disable Metrics/ClassLength
|
8
8
|
# Error class when a wildcard value is missing for a route.
|
9
9
|
class MissingWildcardError < StandardError; end
|
10
10
|
|
@@ -37,18 +37,18 @@ module Cuprum::Rails
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def define_collection_route(action_name, original_path)
|
40
|
-
define_method :"#{action_name}_path" do
|
40
|
+
define_method :"#{action_name}_path" do |**wildcards|
|
41
41
|
path = resolve_base_path(original_path)
|
42
42
|
|
43
|
-
insert_wildcards(path)
|
43
|
+
insert_wildcards(path, **wildcards)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
def define_member_route(action_name, original_path)
|
48
|
-
define_method :"#{action_name}_path" do |entity|
|
48
|
+
define_method :"#{action_name}_path" do |entity = nil, **wildcards|
|
49
49
|
path = resolve_base_path(original_path)
|
50
50
|
|
51
|
-
insert_wildcards(path, entity)
|
51
|
+
insert_wildcards(path, entity, **wildcards)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -75,10 +75,12 @@ module Cuprum::Rails
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
# @param base_path [String]
|
79
|
-
|
80
|
-
|
81
|
-
@
|
78
|
+
# @param base_path [String] the relative path of the resource.
|
79
|
+
# @param parent_path [String] the path to the parent resource, if any.
|
80
|
+
def initialize(base_path:, parent_path: nil, &block)
|
81
|
+
@base_path = base_path
|
82
|
+
@parent_path = parent_path
|
83
|
+
@wildcards = {}
|
82
84
|
|
83
85
|
singleton_class.instance_exec(&block) if block_given?
|
84
86
|
end
|
@@ -91,7 +93,9 @@ module Cuprum::Rails
|
|
91
93
|
|
92
94
|
# @return [String] the path to the parent resource index.
|
93
95
|
def parent_path
|
94
|
-
|
96
|
+
return '/' if @parent_path.nil?
|
97
|
+
|
98
|
+
insert_wildcards(@parent_path)
|
95
99
|
end
|
96
100
|
|
97
101
|
# @return [String] the root path for the application.
|
@@ -120,15 +124,15 @@ module Cuprum::Rails
|
|
120
124
|
|
121
125
|
private
|
122
126
|
|
123
|
-
def insert_wildcards(path,
|
127
|
+
def insert_wildcards(path, value_or_entity = nil, **wildcards)
|
128
|
+
wildcards = wildcards.merge('id' => value_or_entity) if value_or_entity
|
129
|
+
|
124
130
|
path
|
125
131
|
.split('/')
|
126
132
|
.map do |segment|
|
127
133
|
next segment unless segment.start_with?(':')
|
128
134
|
|
129
|
-
|
130
|
-
|
131
|
-
resolve_wildcard(segment)
|
135
|
+
resolve_wildcard(segment, **wildcards)
|
132
136
|
end
|
133
137
|
.join('/')
|
134
138
|
end
|
@@ -141,24 +145,33 @@ module Cuprum::Rails
|
|
141
145
|
"#{base_path}/#{path}"
|
142
146
|
end
|
143
147
|
|
144
|
-
def resolve_primary_key(
|
145
|
-
raise MissingWildcardError, 'missing wildcard :id' if
|
148
|
+
def resolve_primary_key(value_or_entity)
|
149
|
+
raise MissingWildcardError, 'missing wildcard :id' if value_or_entity.nil?
|
150
|
+
|
151
|
+
unless value_or_entity.class.respond_to?(:primary_key)
|
152
|
+
return value_or_entity
|
153
|
+
end
|
146
154
|
|
147
|
-
primary_key =
|
155
|
+
primary_key = value_or_entity.class.primary_key
|
148
156
|
|
149
|
-
|
157
|
+
value_or_entity[primary_key]
|
150
158
|
end
|
151
159
|
|
152
|
-
def resolve_wildcard(segment)
|
160
|
+
def resolve_wildcard(segment, **wildcards)
|
161
|
+
wildcards = self.wildcards.merge(wildcards)
|
162
|
+
value = wildcard_value(segment, **wildcards)
|
163
|
+
|
164
|
+
resolve_primary_key(value)
|
165
|
+
end
|
166
|
+
|
167
|
+
def wildcard_value(segment, **wildcards)
|
153
168
|
wildcard = segment[1..] # :something_id to something_id
|
154
169
|
|
155
|
-
return wildcards[wildcard] if wildcards.
|
170
|
+
return wildcards[wildcard] if wildcards.key?(wildcard)
|
156
171
|
|
157
172
|
wildcard = segment[1...-3] # :something_id to something
|
158
173
|
|
159
|
-
if wildcards.
|
160
|
-
return resolve_primary_key(wildcards[wildcard])
|
161
|
-
end
|
174
|
+
return wildcards[wildcard] if wildcards.key?(wildcard)
|
162
175
|
|
163
176
|
raise MissingWildcardError, "missing wildcard #{segment}"
|
164
177
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cuprum::Rails::RSpec
|
4
|
+
# Helper methods for defining RSpec contracts.
|
5
|
+
module ContractHelpers
|
6
|
+
class << self
|
7
|
+
# Resolves a configuration option.
|
8
|
+
#
|
9
|
+
# If the configured value is a Proc, the Proc is executed in the context
|
10
|
+
# of the example group and the resulting value returned. Otherwise,
|
11
|
+
# returns the configured value, or the given default if the configured
|
12
|
+
# value is nil.
|
13
|
+
#
|
14
|
+
# @param value [Object] The configured value for the option.
|
15
|
+
# @param context [RSpec::SleepingKingStudios::ExampleGroup] The example
|
16
|
+
# group used as a context if the configured value is a Proc.
|
17
|
+
# @param default [Object] An optional default value if the configured
|
18
|
+
# value is nil.
|
19
|
+
def option_with_default(value, context:, default: nil)
|
20
|
+
# :nocov:
|
21
|
+
case value
|
22
|
+
when Proc
|
23
|
+
return context.instance_exec(&value) if value.arity.zero?
|
24
|
+
|
25
|
+
context.instance_exec(default, &value)
|
26
|
+
when nil
|
27
|
+
default
|
28
|
+
else
|
29
|
+
value
|
30
|
+
end
|
31
|
+
# :nocov:
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Resolves a configuration option.
|
36
|
+
#
|
37
|
+
# If the configured value is a Proc, the Proc is executed in the context of
|
38
|
+
# the example group and the resulting value returned. Otherwise, returns the
|
39
|
+
# configured value, or the given default if the configured value is nil.
|
40
|
+
#
|
41
|
+
# @param value [Object] The configured value for the option.
|
42
|
+
# @param context [RSpec::SleepingKingStudios::ExampleGroup] The example
|
43
|
+
# group used as a context if the configured value is a Proc.
|
44
|
+
# @param default [Object] An optional default value if the configured value
|
45
|
+
# is nil.
|
46
|
+
def option_with_default(value, context: nil, default: nil)
|
47
|
+
# :nocov:
|
48
|
+
Cuprum::Rails::RSpec::ContractHelpers
|
49
|
+
.option_with_default(
|
50
|
+
value,
|
51
|
+
context: context || self,
|
52
|
+
default: default
|
53
|
+
)
|
54
|
+
# :nocov:
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|