cuprum-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|