cuprum-rails 0.1.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 +7 -0
- data/CHANGELOG.md +98 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +28 -0
- data/LICENSE +22 -0
- data/README.md +1045 -0
- data/lib/cuprum/rails/action.rb +45 -0
- data/lib/cuprum/rails/actions/create.rb +49 -0
- data/lib/cuprum/rails/actions/destroy.rb +22 -0
- data/lib/cuprum/rails/actions/edit.rb +22 -0
- data/lib/cuprum/rails/actions/index.rb +55 -0
- data/lib/cuprum/rails/actions/new.rb +19 -0
- data/lib/cuprum/rails/actions/resource_action.rb +75 -0
- data/lib/cuprum/rails/actions/show.rb +22 -0
- data/lib/cuprum/rails/actions/update.rb +59 -0
- data/lib/cuprum/rails/actions.rb +16 -0
- data/lib/cuprum/rails/collection.rb +115 -0
- data/lib/cuprum/rails/command.rb +137 -0
- data/lib/cuprum/rails/commands/assign_one.rb +66 -0
- data/lib/cuprum/rails/commands/build_one.rb +55 -0
- data/lib/cuprum/rails/commands/destroy_one.rb +43 -0
- data/lib/cuprum/rails/commands/find_many.rb +60 -0
- data/lib/cuprum/rails/commands/find_matching.rb +121 -0
- data/lib/cuprum/rails/commands/find_one.rb +50 -0
- data/lib/cuprum/rails/commands/insert_one.rb +41 -0
- data/lib/cuprum/rails/commands/update_one.rb +49 -0
- data/lib/cuprum/rails/commands/validate_one.rb +68 -0
- data/lib/cuprum/rails/commands.rb +18 -0
- data/lib/cuprum/rails/controller.rb +50 -0
- data/lib/cuprum/rails/controller_action.rb +121 -0
- data/lib/cuprum/rails/controllers/class_methods/actions.rb +57 -0
- data/lib/cuprum/rails/controllers/class_methods/configuration.rb +64 -0
- data/lib/cuprum/rails/controllers/class_methods/validations.rb +30 -0
- data/lib/cuprum/rails/controllers/class_methods.rb +15 -0
- data/lib/cuprum/rails/controllers/configuration.rb +53 -0
- data/lib/cuprum/rails/controllers.rb +10 -0
- data/lib/cuprum/rails/errors/missing_parameters.rb +33 -0
- data/lib/cuprum/rails/errors/missing_primary_key.rb +46 -0
- data/lib/cuprum/rails/errors/undefined_permitted_attributes.rb +34 -0
- data/lib/cuprum/rails/errors.rb +8 -0
- data/lib/cuprum/rails/map_errors.rb +44 -0
- data/lib/cuprum/rails/query.rb +77 -0
- data/lib/cuprum/rails/query_builder.rb +78 -0
- data/lib/cuprum/rails/repository.rb +44 -0
- data/lib/cuprum/rails/request.rb +105 -0
- data/lib/cuprum/rails/resource.rb +145 -0
- data/lib/cuprum/rails/responders/actions.rb +73 -0
- data/lib/cuprum/rails/responders/html/plural_resource.rb +62 -0
- data/lib/cuprum/rails/responders/html/singular_resource.rb +59 -0
- data/lib/cuprum/rails/responders/html.rb +11 -0
- data/lib/cuprum/rails/responders/html_responder.rb +129 -0
- data/lib/cuprum/rails/responders/json/resource.rb +60 -0
- data/lib/cuprum/rails/responders/json.rb +10 -0
- data/lib/cuprum/rails/responders/json_responder.rb +122 -0
- data/lib/cuprum/rails/responders/matching.rb +145 -0
- data/lib/cuprum/rails/responders/serialization.rb +36 -0
- data/lib/cuprum/rails/responders.rb +15 -0
- data/lib/cuprum/rails/responses/html/redirect_response.rb +29 -0
- data/lib/cuprum/rails/responses/html/render_response.rb +52 -0
- data/lib/cuprum/rails/responses/html.rb +11 -0
- data/lib/cuprum/rails/responses/json_response.rb +29 -0
- data/lib/cuprum/rails/responses.rb +11 -0
- data/lib/cuprum/rails/routes.rb +166 -0
- data/lib/cuprum/rails/routing/plural_routes.rb +26 -0
- data/lib/cuprum/rails/routing/singular_routes.rb +24 -0
- data/lib/cuprum/rails/routing.rb +11 -0
- data/lib/cuprum/rails/rspec/command_contract.rb +460 -0
- data/lib/cuprum/rails/rspec/define_route_contract.rb +84 -0
- data/lib/cuprum/rails/rspec.rb +8 -0
- data/lib/cuprum/rails/serializers/json/active_record_serializer.rb +24 -0
- data/lib/cuprum/rails/serializers/json/array_serializer.rb +40 -0
- data/lib/cuprum/rails/serializers/json/attributes_serializer.rb +217 -0
- data/lib/cuprum/rails/serializers/json/error_serializer.rb +24 -0
- data/lib/cuprum/rails/serializers/json/hash_serializer.rb +44 -0
- data/lib/cuprum/rails/serializers/json/identity_serializer.rb +21 -0
- data/lib/cuprum/rails/serializers/json/serializer.rb +66 -0
- data/lib/cuprum/rails/serializers/json.rb +40 -0
- data/lib/cuprum/rails/serializers.rb +10 -0
- data/lib/cuprum/rails/version.rb +59 -0
- data/lib/cuprum/rails.rb +31 -0
- metadata +286 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/command'
|
4
|
+
|
5
|
+
require 'cuprum/rails'
|
6
|
+
|
7
|
+
module Cuprum::Rails
|
8
|
+
# Abstract command that implement a controller action.
|
9
|
+
class Action < Cuprum::Command
|
10
|
+
# @param resource [Cuprum::Rails::Resource] The controller resource.
|
11
|
+
def initialize(resource:)
|
12
|
+
super()
|
13
|
+
|
14
|
+
@resource = resource
|
15
|
+
end
|
16
|
+
|
17
|
+
# @!method call(request:)
|
18
|
+
# Performs the controller action.
|
19
|
+
#
|
20
|
+
# Subclasses should implement a #process method with the :request keyword,
|
21
|
+
# which accepts an ActionDispatch::Request instance.
|
22
|
+
#
|
23
|
+
# @param request [ActionDispatch::Request] The Rails request.
|
24
|
+
#
|
25
|
+
# @return [Cuprum::Result] the result of the action.
|
26
|
+
|
27
|
+
# @return [Cuprum::Rails::Resource] the controller resource.
|
28
|
+
attr_reader :resource
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :request
|
33
|
+
|
34
|
+
def params
|
35
|
+
@params ||= ActionController::Parameters.new(request.params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def process(request:)
|
39
|
+
@params = nil
|
40
|
+
@request = request
|
41
|
+
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/errors/failed_validation'
|
4
|
+
|
5
|
+
require 'cuprum/rails/actions'
|
6
|
+
require 'cuprum/rails/actions/resource_action'
|
7
|
+
|
8
|
+
module Cuprum::Rails::Actions
|
9
|
+
# Action to build and insert a resource instance.
|
10
|
+
class Create < Cuprum::Rails::Actions::ResourceAction
|
11
|
+
private
|
12
|
+
|
13
|
+
def create_resource
|
14
|
+
entity = nil
|
15
|
+
|
16
|
+
result = steps do
|
17
|
+
attributes = step { resource_params }
|
18
|
+
entity = step { collection.build_one.call(attributes: attributes) }
|
19
|
+
|
20
|
+
step { collection.validate_one.call(entity: entity) }
|
21
|
+
|
22
|
+
step { collection.insert_one.call(entity: entity) }
|
23
|
+
|
24
|
+
{ singular_resource_name => entity }
|
25
|
+
end
|
26
|
+
|
27
|
+
[entity, result]
|
28
|
+
end
|
29
|
+
|
30
|
+
def failed_validation?(result)
|
31
|
+
result.failure? &&
|
32
|
+
result.error.is_a?(Cuprum::Collections::Errors::FailedValidation)
|
33
|
+
end
|
34
|
+
|
35
|
+
def process(request:)
|
36
|
+
super
|
37
|
+
|
38
|
+
entity, result = create_resource
|
39
|
+
|
40
|
+
return result unless failed_validation?(result)
|
41
|
+
|
42
|
+
Cuprum::Result.new(
|
43
|
+
error: result.error,
|
44
|
+
status: :failure,
|
45
|
+
value: { singular_resource_name => entity }
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/actions'
|
4
|
+
require 'cuprum/rails/actions/resource_action'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Actions
|
7
|
+
# Action to delete a resource instance by primary key.
|
8
|
+
class Destroy < Cuprum::Rails::Actions::ResourceAction
|
9
|
+
private
|
10
|
+
|
11
|
+
def process(request:)
|
12
|
+
super
|
13
|
+
|
14
|
+
primary_key = step { resource_id }
|
15
|
+
entity = step do
|
16
|
+
collection.destroy_one.call(primary_key: primary_key)
|
17
|
+
end
|
18
|
+
|
19
|
+
{ singular_resource_name => entity }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/actions'
|
4
|
+
require 'cuprum/rails/actions/resource_action'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Actions
|
7
|
+
# Action to find a resource instance by primary key.
|
8
|
+
class Edit < Cuprum::Rails::Actions::ResourceAction
|
9
|
+
private
|
10
|
+
|
11
|
+
def process(request:)
|
12
|
+
super
|
13
|
+
|
14
|
+
primary_key = step { resource_id }
|
15
|
+
entity = step do
|
16
|
+
collection.find_one.call(primary_key: primary_key)
|
17
|
+
end
|
18
|
+
|
19
|
+
{ singular_resource_name => entity }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/actions'
|
4
|
+
require 'cuprum/rails/actions/resource_action'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Actions
|
7
|
+
# Action to find and filter resources.
|
8
|
+
class Index < Cuprum::Rails::Actions::ResourceAction
|
9
|
+
def_delegators :@resource,
|
10
|
+
:default_order
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# @note Overload this method to change how the filtering params are defined,
|
15
|
+
# or override the #limit, #offset, #order, #where methods directly.
|
16
|
+
def filter_params
|
17
|
+
tools.hash_tools.convert_keys_to_strings(request.params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def limit
|
21
|
+
filter_params['limit']
|
22
|
+
end
|
23
|
+
|
24
|
+
def offset
|
25
|
+
filter_params['offset']
|
26
|
+
end
|
27
|
+
|
28
|
+
def order
|
29
|
+
filter_params.fetch('order', default_order.presence)
|
30
|
+
end
|
31
|
+
|
32
|
+
def process(request:)
|
33
|
+
super
|
34
|
+
|
35
|
+
filters = where
|
36
|
+
block = where.present? ? -> { filters } : nil
|
37
|
+
|
38
|
+
collection.find_matching.call(
|
39
|
+
envelope: true,
|
40
|
+
limit: limit,
|
41
|
+
offset: offset,
|
42
|
+
order: order,
|
43
|
+
&block
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def tools
|
48
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
49
|
+
end
|
50
|
+
|
51
|
+
def where
|
52
|
+
filter_params['where']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/actions'
|
4
|
+
require 'cuprum/rails/actions/resource_action'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Actions
|
7
|
+
# Action to build an empty resource instance.
|
8
|
+
class New < Cuprum::Rails::Actions::ResourceAction
|
9
|
+
private
|
10
|
+
|
11
|
+
def process(request:)
|
12
|
+
super
|
13
|
+
|
14
|
+
instance = step { collection.build_one.call(attributes: {}) }
|
15
|
+
|
16
|
+
{ singular_resource_name => instance }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
require 'cuprum/rails/actions'
|
6
|
+
require 'cuprum/rails/errors/missing_parameters'
|
7
|
+
require 'cuprum/rails/errors/missing_primary_key'
|
8
|
+
require 'cuprum/rails/errors/undefined_permitted_attributes'
|
9
|
+
|
10
|
+
module Cuprum::Rails::Actions
|
11
|
+
# Abstract base class for resourceful actions.
|
12
|
+
class ResourceAction < Cuprum::Rails::Action
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
# @param resource [Cuprum::Rails::Resource] The controller resource.
|
16
|
+
def initialize(resource:)
|
17
|
+
if resource.collection.nil?
|
18
|
+
raise ArgumentError, 'resource must have a collection'
|
19
|
+
end
|
20
|
+
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def_delegators :@resource,
|
25
|
+
:collection,
|
26
|
+
:resource_name,
|
27
|
+
:singular_resource_name
|
28
|
+
|
29
|
+
# @return [Object] the primary key for the resource.
|
30
|
+
def resource_id
|
31
|
+
return success(params[:id]) if params[:id].present?
|
32
|
+
|
33
|
+
failure(missing_primary_key_error)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Hash] the permitted params for the resource.
|
37
|
+
def resource_params
|
38
|
+
return failure(permitted_attributes_error) unless permitted_attributes?
|
39
|
+
|
40
|
+
success(raw_resource_params)
|
41
|
+
rescue ActionController::ParameterMissing
|
42
|
+
failure(missing_parameters_error)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def missing_parameters_error
|
48
|
+
Cuprum::Rails::Errors::MissingParameters
|
49
|
+
.new(resource_name: singular_resource_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def missing_primary_key_error
|
53
|
+
Cuprum::Rails::Errors::MissingPrimaryKey.new(
|
54
|
+
primary_key: resource.primary_key,
|
55
|
+
resource_name: singular_resource_name
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def permitted_attributes?
|
60
|
+
!resource.permitted_attributes.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def permitted_attributes_error
|
64
|
+
Cuprum::Rails::Errors::UndefinedPermittedAttributes
|
65
|
+
.new(resource_name: singular_resource_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
def raw_resource_params
|
69
|
+
params
|
70
|
+
.require(singular_resource_name)
|
71
|
+
.permit(*resource.permitted_attributes)
|
72
|
+
.to_hash
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails/actions'
|
4
|
+
require 'cuprum/rails/actions/resource_action'
|
5
|
+
|
6
|
+
module Cuprum::Rails::Actions
|
7
|
+
# Action to find a resource instance by primary key.
|
8
|
+
class Show < Cuprum::Rails::Actions::ResourceAction
|
9
|
+
private
|
10
|
+
|
11
|
+
def process(request:)
|
12
|
+
super
|
13
|
+
|
14
|
+
primary_key = step { resource_id }
|
15
|
+
entity = step do
|
16
|
+
collection.find_one.call(primary_key: primary_key)
|
17
|
+
end
|
18
|
+
|
19
|
+
{ singular_resource_name => entity }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/errors/failed_validation'
|
4
|
+
|
5
|
+
require 'cuprum/rails/actions'
|
6
|
+
require 'cuprum/rails/actions/resource_action'
|
7
|
+
|
8
|
+
module Cuprum::Rails::Actions
|
9
|
+
# Action to assign and update a resource instance by primary key.
|
10
|
+
class Update < Cuprum::Rails::Actions::ResourceAction
|
11
|
+
private
|
12
|
+
|
13
|
+
def assign_resource
|
14
|
+
primary_key = step { resource_id }
|
15
|
+
attributes = step { resource_params }
|
16
|
+
entity = step do
|
17
|
+
collection.find_one.call(primary_key: primary_key)
|
18
|
+
end
|
19
|
+
step do
|
20
|
+
collection.assign_one.call(attributes: attributes, entity: entity)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def failed_validation?(result)
|
25
|
+
result.failure? &&
|
26
|
+
result.error.is_a?(Cuprum::Collections::Errors::FailedValidation)
|
27
|
+
end
|
28
|
+
|
29
|
+
def process(request:)
|
30
|
+
super
|
31
|
+
|
32
|
+
entity, result = update_resource
|
33
|
+
|
34
|
+
return result unless failed_validation?(result)
|
35
|
+
|
36
|
+
Cuprum::Result.new(
|
37
|
+
error: result.error,
|
38
|
+
status: :failure,
|
39
|
+
value: { singular_resource_name => entity }
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_resource
|
44
|
+
entity = nil
|
45
|
+
|
46
|
+
result = steps do
|
47
|
+
entity = assign_resource
|
48
|
+
|
49
|
+
step { collection.validate_one.call(entity: entity) }
|
50
|
+
|
51
|
+
step { collection.update_one.call(entity: entity) }
|
52
|
+
|
53
|
+
{ singular_resource_name => entity }
|
54
|
+
end
|
55
|
+
|
56
|
+
[entity, result]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails'
|
4
|
+
|
5
|
+
module Cuprum::Rails
|
6
|
+
# Namespace for defined resourceful actions.
|
7
|
+
module Actions
|
8
|
+
autoload :Create, 'cuprum/rails/actions/create'
|
9
|
+
autoload :Destroy, 'cuprum/rails/actions/destroy'
|
10
|
+
autoload :Edit, 'cuprum/rails/actions/edit'
|
11
|
+
autoload :Index, 'cuprum/rails/actions/index'
|
12
|
+
autoload :New, 'cuprum/rails/actions/new'
|
13
|
+
autoload :Show, 'cuprum/rails/actions/show'
|
14
|
+
autoload :Update, 'cuprum/rails/actions/update'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/command_factory'
|
4
|
+
|
5
|
+
require 'cuprum/rails'
|
6
|
+
|
7
|
+
module Cuprum::Rails
|
8
|
+
# Wraps an ActiveRecord model as a Cuprum collection.
|
9
|
+
class Collection < Cuprum::CommandFactory
|
10
|
+
# @param collection_name [String, Symbol] The name of the collection.
|
11
|
+
# @param member_name [String] The name of a collection entity.
|
12
|
+
# @param options [Hash<Symbol>] Additional options for the command.
|
13
|
+
# @param record_class [Class] The ActiveRecord class for the collection.
|
14
|
+
def initialize(
|
15
|
+
record_class:,
|
16
|
+
collection_name: nil,
|
17
|
+
member_name: nil,
|
18
|
+
**options
|
19
|
+
)
|
20
|
+
super()
|
21
|
+
|
22
|
+
@collection_name = resolve_collection_name(collection_name, record_class)
|
23
|
+
@member_name = resolve_member_name(@collection_name, member_name)
|
24
|
+
@record_class = record_class
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [String] The name of the collection.
|
29
|
+
attr_reader :collection_name
|
30
|
+
|
31
|
+
# @return [String] the name of a collection entity.
|
32
|
+
attr_reader :member_name
|
33
|
+
|
34
|
+
# @return [Hash<Symbol>] additional options for the command.
|
35
|
+
attr_reader :options
|
36
|
+
|
37
|
+
# @return [Class] the ActiveRecord class for the collection.
|
38
|
+
attr_reader :record_class
|
39
|
+
|
40
|
+
command_class :assign_one do
|
41
|
+
Cuprum::Rails::Commands::AssignOne
|
42
|
+
.subclass(**command_options)
|
43
|
+
end
|
44
|
+
|
45
|
+
command_class :build_one do
|
46
|
+
Cuprum::Rails::Commands::BuildOne
|
47
|
+
.subclass(**command_options)
|
48
|
+
end
|
49
|
+
|
50
|
+
command_class :destroy_one do
|
51
|
+
Cuprum::Rails::Commands::DestroyOne
|
52
|
+
.subclass(**command_options)
|
53
|
+
end
|
54
|
+
|
55
|
+
command_class :find_many do
|
56
|
+
Cuprum::Rails::Commands::FindMany
|
57
|
+
.subclass(**command_options)
|
58
|
+
end
|
59
|
+
|
60
|
+
command_class :find_matching do
|
61
|
+
Cuprum::Rails::Commands::FindMatching
|
62
|
+
.subclass(**command_options)
|
63
|
+
end
|
64
|
+
|
65
|
+
command_class :find_one do
|
66
|
+
Cuprum::Rails::Commands::FindOne
|
67
|
+
.subclass(**command_options)
|
68
|
+
end
|
69
|
+
|
70
|
+
command_class :insert_one do
|
71
|
+
Cuprum::Rails::Commands::InsertOne
|
72
|
+
.subclass(**command_options)
|
73
|
+
end
|
74
|
+
|
75
|
+
command_class :update_one do
|
76
|
+
Cuprum::Rails::Commands::UpdateOne
|
77
|
+
.subclass(**command_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
command_class :validate_one do
|
81
|
+
Cuprum::Rails::Commands::ValidateOne
|
82
|
+
.subclass(**command_options)
|
83
|
+
end
|
84
|
+
|
85
|
+
# A new Query instance, used for querying against the collection data.
|
86
|
+
#
|
87
|
+
# @return [Cuprum::Rails::Query] the query.
|
88
|
+
def query
|
89
|
+
Cuprum::Rails::Query.new(record_class)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def command_options
|
95
|
+
@command_options ||= {
|
96
|
+
collection_name: collection_name,
|
97
|
+
member_name: member_name,
|
98
|
+
record_class: record_class,
|
99
|
+
**options
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def resolve_collection_name(collection_name, record_class)
|
104
|
+
return collection_name.to_s unless collection_name.nil?
|
105
|
+
|
106
|
+
record_class.name.underscore.pluralize
|
107
|
+
end
|
108
|
+
|
109
|
+
def resolve_member_name(collection_name, member_name)
|
110
|
+
return member_name.to_s unless member_name.nil?
|
111
|
+
|
112
|
+
collection_name.singularize
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/rails'
|
4
|
+
|
5
|
+
module Cuprum::Rails
|
6
|
+
# Abstract base class for Rails collection commands.
|
7
|
+
class Command < Cuprum::Collections::Command
|
8
|
+
# Creates a subclass with the given parameters applied to the constructor.
|
9
|
+
def self.subclass(**default_options)
|
10
|
+
Class.new(self) do
|
11
|
+
define_method(:initialize) do |**options|
|
12
|
+
super(**default_options.merge(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param collection_name [String, Symbol] The name of the collection.
|
18
|
+
# @param member_name [String] The name of a collection entity.
|
19
|
+
# @param options [Hash<Symbol>] Additional options for the command.
|
20
|
+
# @param record_class [Class] The ActiveRecord class for the collection.
|
21
|
+
def initialize(
|
22
|
+
record_class:,
|
23
|
+
collection_name: nil,
|
24
|
+
member_name: nil,
|
25
|
+
**options
|
26
|
+
)
|
27
|
+
super()
|
28
|
+
|
29
|
+
@collection_name = resolve_collection_name(collection_name, record_class)
|
30
|
+
@member_name = resolve_member_name(@collection_name, member_name)
|
31
|
+
@record_class = record_class
|
32
|
+
@options = options
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String] The name of the collection.
|
36
|
+
attr_reader :collection_name
|
37
|
+
|
38
|
+
# @return [String] the name of a collection entity.
|
39
|
+
attr_reader :member_name
|
40
|
+
|
41
|
+
# @return [Hash<Symbol>] additional options for the command.
|
42
|
+
attr_reader :options
|
43
|
+
|
44
|
+
# @return [Class] the ActiveRecord class for the collection.
|
45
|
+
attr_reader :record_class
|
46
|
+
|
47
|
+
# @return [Symbol] the name of the primary key attribute.
|
48
|
+
def primary_key_name
|
49
|
+
@primary_key_name ||= record_class.primary_key.intern
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Class] the type of the primary key attribute.
|
53
|
+
def primary_key_type
|
54
|
+
@primary_key_type ||=
|
55
|
+
case primary_key_column_type
|
56
|
+
when :integer
|
57
|
+
Integer
|
58
|
+
when :uuid
|
59
|
+
String
|
60
|
+
else
|
61
|
+
# :nocov:
|
62
|
+
raise "unknown primary key column type :#{primary_key_column_type}"
|
63
|
+
# :nocov:
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def entity_contract
|
70
|
+
type = record_class
|
71
|
+
|
72
|
+
@entity_contract ||= Stannum::Contracts::ParametersContract.new do
|
73
|
+
keyword :entity, type
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def primary_key_contract
|
78
|
+
type = primary_key_type
|
79
|
+
|
80
|
+
@primary_key_contract ||= Stannum::Contracts::ParametersContract.new do
|
81
|
+
keyword :primary_key, type
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def primary_key_column_type
|
86
|
+
record_class
|
87
|
+
.columns
|
88
|
+
.find { |column| column.name == record_class.primary_key }
|
89
|
+
.type
|
90
|
+
end
|
91
|
+
|
92
|
+
def primary_keys_contract
|
93
|
+
type = primary_key_type
|
94
|
+
|
95
|
+
@primary_keys_contract ||= Stannum::Contracts::ParametersContract.new do
|
96
|
+
keyword :primary_keys,
|
97
|
+
Stannum::Constraints::Types::ArrayType.new(item_type: type)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def resolve_collection_name(collection_name, record_class)
|
102
|
+
return collection_name.to_s unless collection_name.nil?
|
103
|
+
|
104
|
+
record_class.name.underscore.pluralize
|
105
|
+
end
|
106
|
+
|
107
|
+
def resolve_member_name(collection_name, member_name)
|
108
|
+
return member_name.to_s unless member_name.nil?
|
109
|
+
|
110
|
+
collection_name.singularize
|
111
|
+
end
|
112
|
+
|
113
|
+
def validate_entity(entity)
|
114
|
+
match_parameters_to_contract(
|
115
|
+
contract: entity_contract,
|
116
|
+
keywords: { entity: entity },
|
117
|
+
method_name: :call
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
def validate_primary_key(primary_key)
|
122
|
+
match_parameters_to_contract(
|
123
|
+
contract: primary_key_contract,
|
124
|
+
keywords: { primary_key: primary_key },
|
125
|
+
method_name: :call
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate_primary_keys(primary_keys)
|
130
|
+
match_parameters_to_contract(
|
131
|
+
contract: primary_keys_contract,
|
132
|
+
keywords: { primary_keys: primary_keys },
|
133
|
+
method_name: :call
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|