wallaby-core 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/LICENSE +21 -0
- data/README.md +31 -0
- data/app/controllers/wallaby/application_controller.rb +84 -0
- data/app/controllers/wallaby/resources_controller.rb +381 -0
- data/app/controllers/wallaby/secure_controller.rb +81 -0
- data/app/security/ability.rb +13 -0
- data/config/locales/wallaby.en.yml +140 -0
- data/config/locales/wallaby_class.en.yml +30 -0
- data/config/routes.rb +39 -0
- data/lib/adaptors/wallaby/custom.rb +7 -0
- data/lib/adaptors/wallaby/custom/default_provider.rb +9 -0
- data/lib/adaptors/wallaby/custom/model_decorator.rb +71 -0
- data/lib/adaptors/wallaby/custom/model_finder.rb +13 -0
- data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +14 -0
- data/lib/adaptors/wallaby/custom/model_service_provider.rb +48 -0
- data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +72 -0
- data/lib/authorizers/wallaby/default_authorization_provider.rb +58 -0
- data/lib/authorizers/wallaby/model_authorizer.rb +100 -0
- data/lib/authorizers/wallaby/pundit_authorization_provider.rb +89 -0
- data/lib/concerns/wallaby/authorizable.rb +103 -0
- data/lib/concerns/wallaby/baseable.rb +36 -0
- data/lib/concerns/wallaby/decoratable.rb +101 -0
- data/lib/concerns/wallaby/defaultable.rb +38 -0
- data/lib/concerns/wallaby/engineable.rb +61 -0
- data/lib/concerns/wallaby/fieldable.rb +78 -0
- data/lib/concerns/wallaby/paginatable.rb +72 -0
- data/lib/concerns/wallaby/rails_overridden_methods.rb +42 -0
- data/lib/concerns/wallaby/resourcable.rb +149 -0
- data/lib/concerns/wallaby/servicable.rb +68 -0
- data/lib/concerns/wallaby/shared_helpers.rb +22 -0
- data/lib/concerns/wallaby/themeable.rb +40 -0
- data/lib/decorators/wallaby/resource_decorator.rb +189 -0
- data/lib/errors/wallaby/cell_handling.rb +6 -0
- data/lib/errors/wallaby/forbidden.rb +6 -0
- data/lib/errors/wallaby/general_error.rb +6 -0
- data/lib/errors/wallaby/invalid_error.rb +6 -0
- data/lib/errors/wallaby/model_not_found.rb +11 -0
- data/lib/errors/wallaby/not_authenticated.rb +6 -0
- data/lib/errors/wallaby/not_found.rb +6 -0
- data/lib/errors/wallaby/not_implemented.rb +6 -0
- data/lib/errors/wallaby/resource_not_found.rb +11 -0
- data/lib/errors/wallaby/unprocessable_entity.rb +6 -0
- data/lib/forms/wallaby/form_builder.rb +60 -0
- data/lib/helpers/wallaby/application_helper.rb +79 -0
- data/lib/helpers/wallaby/base_helper.rb +65 -0
- data/lib/helpers/wallaby/configuration_helper.rb +18 -0
- data/lib/helpers/wallaby/form_helper.rb +62 -0
- data/lib/helpers/wallaby/index_helper.rb +84 -0
- data/lib/helpers/wallaby/links_helper.rb +213 -0
- data/lib/helpers/wallaby/resources_helper.rb +52 -0
- data/lib/helpers/wallaby/secure_helper.rb +54 -0
- data/lib/helpers/wallaby/styling_helper.rb +82 -0
- data/lib/interfaces/wallaby/mode.rb +72 -0
- data/lib/interfaces/wallaby/model_authorization_provider.rb +99 -0
- data/lib/interfaces/wallaby/model_decorator.rb +168 -0
- data/lib/interfaces/wallaby/model_finder.rb +12 -0
- data/lib/interfaces/wallaby/model_pagination_provider.rb +107 -0
- data/lib/interfaces/wallaby/model_service_provider.rb +84 -0
- data/lib/paginators/wallaby/model_paginator.rb +115 -0
- data/lib/paginators/wallaby/resource_paginator.rb +12 -0
- data/lib/parsers/wallaby/parser.rb +34 -0
- data/lib/renderers/wallaby/cell.rb +137 -0
- data/lib/renderers/wallaby/cell_resolver.rb +89 -0
- data/lib/renderers/wallaby/custom_lookup_context.rb +64 -0
- data/lib/renderers/wallaby/custom_partial_renderer.rb +33 -0
- data/lib/renderers/wallaby/custom_renderer.rb +16 -0
- data/lib/responders/wallaby/json_api_responder.rb +101 -0
- data/lib/responders/wallaby/resources_responder.rb +28 -0
- data/lib/routes/wallaby/resources_router.rb +72 -0
- data/lib/servicers/wallaby/model_servicer.rb +154 -0
- data/lib/services/wallaby/engine_name_finder.rb +22 -0
- data/lib/services/wallaby/engine_url_for.rb +46 -0
- data/lib/services/wallaby/link_options_normalizer.rb +19 -0
- data/lib/services/wallaby/map/mode_mapper.rb +27 -0
- data/lib/services/wallaby/map/model_class_collector.rb +49 -0
- data/lib/services/wallaby/map/model_class_mapper.rb +38 -0
- data/lib/services/wallaby/prefixes_builder.rb +66 -0
- data/lib/services/wallaby/sorting/hash_builder.rb +19 -0
- data/lib/services/wallaby/sorting/link_builder.rb +69 -0
- data/lib/services/wallaby/sorting/next_builder.rb +63 -0
- data/lib/services/wallaby/sorting/single_builder.rb +20 -0
- data/lib/services/wallaby/type_renderer.rb +50 -0
- data/lib/support/action_dispatch/routing/mapper.rb +75 -0
- data/lib/tree/wallaby/node.rb +25 -0
- data/lib/utils/wallaby/cell_utils.rb +34 -0
- data/lib/utils/wallaby/field_utils.rb +43 -0
- data/lib/utils/wallaby/filter_utils.rb +20 -0
- data/lib/utils/wallaby/model_utils.rb +51 -0
- data/lib/utils/wallaby/module_utils.rb +46 -0
- data/lib/utils/wallaby/params_utils.rb +14 -0
- data/lib/utils/wallaby/preload_utils.rb +44 -0
- data/lib/utils/wallaby/test_utils.rb +34 -0
- data/lib/utils/wallaby/utils.rb +27 -0
- data/lib/wallaby/configuration.rb +103 -0
- data/lib/wallaby/configuration/features.rb +24 -0
- data/lib/wallaby/configuration/mapping.rb +140 -0
- data/lib/wallaby/configuration/metadata.rb +23 -0
- data/lib/wallaby/configuration/models.rb +46 -0
- data/lib/wallaby/configuration/pagination.rb +30 -0
- data/lib/wallaby/configuration/security.rb +98 -0
- data/lib/wallaby/configuration/sorting.rb +28 -0
- data/lib/wallaby/constants.rb +45 -0
- data/lib/wallaby/core.rb +117 -0
- data/lib/wallaby/core/version.rb +7 -0
- data/lib/wallaby/engine.rb +43 -0
- data/lib/wallaby/map.rb +170 -0
- metadata +222 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Decorator related attributes
|
|
5
|
+
module Decoratable
|
|
6
|
+
# Configurable attribute
|
|
7
|
+
module ClassMethods
|
|
8
|
+
# @!attribute [w] resource_decorator
|
|
9
|
+
def resource_decorator=(resource_decorator)
|
|
10
|
+
ModuleUtils.inheritance_check resource_decorator, application_decorator
|
|
11
|
+
@resource_decorator = resource_decorator
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @!attribute [r] resource_decorator
|
|
15
|
+
# Resource decorator will be used for its metadata info and decoration methods.
|
|
16
|
+
#
|
|
17
|
+
# If Wallaby doesn't get it right, please specify the **resource_decorator**.
|
|
18
|
+
# @example To set resource decorator
|
|
19
|
+
# class Admin::ProductionsController < Admin::ApplicationController
|
|
20
|
+
# self.resource_decorator = ProductDecorator
|
|
21
|
+
# end
|
|
22
|
+
# @return [Class] resource decorator
|
|
23
|
+
# @raise [ArgumentError] when **resource_decorator** doesn't inherit from **application_decorator**
|
|
24
|
+
# @see Wallaby::ResourceDecorator
|
|
25
|
+
# @since 5.2.0
|
|
26
|
+
attr_reader :resource_decorator
|
|
27
|
+
|
|
28
|
+
# @!attribute [w] application_decorator
|
|
29
|
+
def application_decorator=(application_decorator)
|
|
30
|
+
ModuleUtils.inheritance_check resource_decorator, application_decorator
|
|
31
|
+
@application_decorator = application_decorator
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @!attribute [r] application_decorator
|
|
35
|
+
# The **application_decorator** is as the base class of {#resource_decorator}.
|
|
36
|
+
# @example To set application decorator:
|
|
37
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
|
38
|
+
# self.application_decorator = AnotherApplicationDecorator
|
|
39
|
+
# end
|
|
40
|
+
# @raise [ArgumentError] when **resource_decorator** doesn't inherit from **application_decorator**
|
|
41
|
+
# @return [Class] application decorator
|
|
42
|
+
# @see Wallaby::ResourceDecorator
|
|
43
|
+
# @since 5.2.0
|
|
44
|
+
def application_decorator
|
|
45
|
+
@application_decorator ||= ModuleUtils.try_to superclass, :application_decorator
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get current model decorator. It comes from
|
|
50
|
+
#
|
|
51
|
+
# - model decorator for {Wallaby::Decoratable::ClassMethods#resource_decorator resource_decorator}
|
|
52
|
+
# - otherwise, model decorator for {Wallaby::Decoratable::ClassMethods#application_decorator application_decorator}
|
|
53
|
+
#
|
|
54
|
+
# Model decorator stores the information of **metadata** and **field_names** for **index**/**show**/**form** action.
|
|
55
|
+
# @return [Wallaby::ModelDecorator] current model decorator for this request
|
|
56
|
+
def current_model_decorator
|
|
57
|
+
@current_model_decorator ||=
|
|
58
|
+
current_decorator.try(:model_decorator) || \
|
|
59
|
+
Map.model_decorator_map(current_model_class, controller_to_get(:application_decorator))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Get current resource decorator. It comes from
|
|
63
|
+
#
|
|
64
|
+
# - {Wallaby::Decoratable::ClassMethods#resource_decorator resource_decorator}
|
|
65
|
+
# - otherwise, {Wallaby::Decoratable::ClassMethods#application_decorator application_decorator}
|
|
66
|
+
# @return [Wallaby::ResourceDecorator] current resource decorator for this request
|
|
67
|
+
def current_decorator
|
|
68
|
+
@current_decorator ||=
|
|
69
|
+
(controller_to_get(:resource_decorator) || \
|
|
70
|
+
Map.resource_decorator_map(current_model_class, controller_to_get(:application_decorator))).tap do |decorator|
|
|
71
|
+
Rails.logger.info %( - Current decorator: #{decorator})
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Get current fields metadata for current action name.
|
|
76
|
+
# @return [Hash] current fields metadata
|
|
77
|
+
def current_fields
|
|
78
|
+
@current_fields ||=
|
|
79
|
+
ModuleUtils.try_to current_model_decorator, :"#{FORM_ACTIONS[action_name] || action_name}_fields"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Wrap resource(s) with decorator(s).
|
|
83
|
+
# @param resource [Object, Enumerable]
|
|
84
|
+
# @return [Wallaby::ResourceDecorator, Enumerable<Wallaby::ResourceDecorator>] decorator(s)
|
|
85
|
+
def decorate(resource)
|
|
86
|
+
return resource if resource.is_a? ResourceDecorator
|
|
87
|
+
return resource.map { |item| decorate item } if resource.respond_to? :map
|
|
88
|
+
|
|
89
|
+
decorator = Map.resource_decorator_map resource.class, controller_to_get(:application_decorator)
|
|
90
|
+
decorator ? decorator.new(resource) : resource
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @param resource [Object, Wallaby::ResourceDecorator]
|
|
94
|
+
# @return [Object] the unwrapped resource object
|
|
95
|
+
def extract(resource)
|
|
96
|
+
return resource.resource if resource.is_a? ResourceDecorator
|
|
97
|
+
|
|
98
|
+
resource
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Defaults related methods
|
|
5
|
+
module Defaultable
|
|
6
|
+
protected
|
|
7
|
+
|
|
8
|
+
# Set default options for create action
|
|
9
|
+
# @param options [Hash]
|
|
10
|
+
# @return [Hash] updated options with default values
|
|
11
|
+
def set_defaults_for(action, options)
|
|
12
|
+
case action.try(:to_sym)
|
|
13
|
+
when :create, :update then assign_create_and_update_defaults_with options
|
|
14
|
+
when :destroy then assign_destroy_defaults_with options
|
|
15
|
+
end
|
|
16
|
+
options
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param options [Hash]
|
|
20
|
+
# @return [Hash] updated options with default values
|
|
21
|
+
def assign_create_and_update_defaults_with(options)
|
|
22
|
+
options[:params] ||= resource_params
|
|
23
|
+
options[:location] ||= -> { helpers.show_path resource, is_resource: params[:resource] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @param options [Hash]
|
|
27
|
+
# @return [Hash] updated options with default values
|
|
28
|
+
def assign_destroy_defaults_with(options)
|
|
29
|
+
options[:params] ||= params
|
|
30
|
+
options[:location] ||=
|
|
31
|
+
if params[:resource]
|
|
32
|
+
helpers.show_path resource, is_resource: params[:resource]
|
|
33
|
+
else
|
|
34
|
+
helpers.index_path current_model_class
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Engine related helper methods for both controller and view
|
|
5
|
+
module Engineable
|
|
6
|
+
# Configurable attribute
|
|
7
|
+
module ClassMethods
|
|
8
|
+
# @!attribute [w] engine_name
|
|
9
|
+
attr_writer :engine_name
|
|
10
|
+
|
|
11
|
+
# @!attribute [r] engine_name
|
|
12
|
+
# The engine name will be used to handle URLs.
|
|
13
|
+
#
|
|
14
|
+
# So when to set this engine name? When Wallaby doesn't know what is the correct engine helper to use.
|
|
15
|
+
# @example To set an engine name:
|
|
16
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
|
17
|
+
# self.engine_name = 'admin_engine'
|
|
18
|
+
# end
|
|
19
|
+
# @return [String, Symbol, nil] engine name
|
|
20
|
+
# @since 5.2.0
|
|
21
|
+
def engine_name
|
|
22
|
+
@engine_name ||= ModuleUtils.try_to superclass, :engine_name
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# This engine helper is used to access URL helpers of Wallaby engine.
|
|
27
|
+
#
|
|
28
|
+
# Considering **Wallaby** is mounted at the following paths:
|
|
29
|
+
#
|
|
30
|
+
# ```
|
|
31
|
+
# mount Wallaby::Engine, at: '/admin'
|
|
32
|
+
# mount Wallaby::Engine, at: '/inner', as: :inner_engine, defaults: { resources_controller: InnerController }
|
|
33
|
+
# ```
|
|
34
|
+
#
|
|
35
|
+
# If `/inner` is current script name, `current_engine` is same as `inner_engine`.
|
|
36
|
+
# Then it's possible to access URL helpers like this:
|
|
37
|
+
#
|
|
38
|
+
# ```
|
|
39
|
+
# current_engine.resources_path resources: 'products'
|
|
40
|
+
# ```
|
|
41
|
+
# @return [ActionDispatch::Routing::RoutesProxy] engine for current request
|
|
42
|
+
def current_engine
|
|
43
|
+
@current_engine ||= ModuleUtils.try_to self, current_engine_name
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Find out the engine name under current script name.
|
|
47
|
+
#
|
|
48
|
+
# Considering **Wallaby** is mounted at the following paths:
|
|
49
|
+
#
|
|
50
|
+
# ```
|
|
51
|
+
# mount Wallaby::Engine, at: '/admin'
|
|
52
|
+
# mount Wallaby::Engine, at: '/inner', as: :inner_engine, defaults: { resources_controller: InnerController }
|
|
53
|
+
# ```
|
|
54
|
+
#
|
|
55
|
+
# If `/inner` is current script name, then `current_engine_name` returns `'inner_engine'`.
|
|
56
|
+
# @return [String] engine name for current request
|
|
57
|
+
def current_engine_name
|
|
58
|
+
@current_engine_name ||= controller_to_get(__callee__, :engine_name) || EngineNameFinder.find(request.env)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Field helper for model decorator
|
|
5
|
+
module Fieldable
|
|
6
|
+
# @param field_name [String, Symbol] field name
|
|
7
|
+
# @return [Hash] metadata information for a given field
|
|
8
|
+
def metadata_of(field_name)
|
|
9
|
+
fields[field_name] || {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @param field_name [String, Symbol] field name
|
|
13
|
+
# @return [String] label for a given field
|
|
14
|
+
def label_of(field_name)
|
|
15
|
+
metadata_of(field_name)[:label] || field_name.to_s.humanize
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @param field_name [String, Symbol] field name
|
|
19
|
+
# @return [String, Symbol] type for a given field
|
|
20
|
+
def type_of(field_name)
|
|
21
|
+
validate_presence_of field_name, metadata_of(field_name)[:type]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param field_name [String, Symbol] field name
|
|
25
|
+
# @return [Hash] index metadata information for a given field
|
|
26
|
+
def index_metadata_of(field_name)
|
|
27
|
+
index_fields[field_name] || {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param field_name [String, Symbol] field name
|
|
31
|
+
# @return [String] index label for a given field
|
|
32
|
+
def index_label_of(field_name)
|
|
33
|
+
index_metadata_of(field_name)[:label] || field_name.to_s.humanize
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param field_name [String, Symbol] field name
|
|
37
|
+
# @return [String, Symbol] index type for a given field
|
|
38
|
+
def index_type_of(field_name)
|
|
39
|
+
validate_presence_of field_name, index_metadata_of(field_name)[:type]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param field_name [String, Symbol] field name
|
|
43
|
+
# @return [Hash] show metadata information for a given field
|
|
44
|
+
def show_metadata_of(field_name)
|
|
45
|
+
show_fields[field_name] || {}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param field_name [String, Symbol] field name
|
|
49
|
+
# @return [String] show label for a given field
|
|
50
|
+
def show_label_of(field_name)
|
|
51
|
+
show_metadata_of(field_name)[:label] || field_name.to_s.humanize
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @param field_name [String, Symbol] field name
|
|
55
|
+
# @return [String, Symbol] show type for a given field
|
|
56
|
+
def show_type_of(field_name)
|
|
57
|
+
validate_presence_of field_name, show_metadata_of(field_name)[:type]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @param field_name [String, Symbol] field name
|
|
61
|
+
# @return [Hash] form metadata information for a given field
|
|
62
|
+
def form_metadata_of(field_name)
|
|
63
|
+
form_fields[field_name] || {}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @param field_name [String, Symbol] field name
|
|
67
|
+
# @return [String] form label for a given field
|
|
68
|
+
def form_label_of(field_name)
|
|
69
|
+
form_metadata_of(field_name)[:label] || field_name.to_s.humanize
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @param field_name [String, Symbol] field name
|
|
73
|
+
# @return [String, Symbol] form type for a given field
|
|
74
|
+
def form_type_of(field_name)
|
|
75
|
+
validate_presence_of field_name, form_metadata_of(field_name)[:type]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Paginator related attributes
|
|
5
|
+
module Paginatable
|
|
6
|
+
# Configurable attribute
|
|
7
|
+
module ClassMethods
|
|
8
|
+
# @!attribute [w] model_paginator
|
|
9
|
+
def model_paginator=(model_paginator)
|
|
10
|
+
ModuleUtils.inheritance_check model_paginator, application_paginator
|
|
11
|
+
@model_paginator = model_paginator
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @!attribute [r] model_paginator
|
|
15
|
+
# If Wallaby doesn't get it right, please specify the **model_paginator**.
|
|
16
|
+
# @example To set model paginator
|
|
17
|
+
# class Admin::ProductionsController < Admin::ApplicationController
|
|
18
|
+
# self.model_paginator = ProductPaginator
|
|
19
|
+
# end
|
|
20
|
+
# @return [Class] model paginator
|
|
21
|
+
# @raise [ArgumentError] when **model_paginator** doesn't inherit from **application_paginator**
|
|
22
|
+
# @see Wallaby::ModelPaginator
|
|
23
|
+
# @since 5.2.0
|
|
24
|
+
attr_reader :model_paginator
|
|
25
|
+
|
|
26
|
+
# @!attribute [w] application_paginator
|
|
27
|
+
def application_paginator=(application_paginator)
|
|
28
|
+
ModuleUtils.inheritance_check model_paginator, application_paginator
|
|
29
|
+
@application_paginator = application_paginator
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @!attribute [r] application_paginator
|
|
33
|
+
# The **application_paginator** is as the base class of {#model_paginator}.
|
|
34
|
+
# @example To set application decorator:
|
|
35
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
|
36
|
+
# self.application_paginator = AnotherApplicationPaginator
|
|
37
|
+
# end
|
|
38
|
+
# @return [Class] application decorator
|
|
39
|
+
# @raise [ArgumentError] when **model_paginator** doesn't inherit from **application_paginator**
|
|
40
|
+
# @see Wallaby::ModelPaginator
|
|
41
|
+
# @since 5.2.0
|
|
42
|
+
def application_paginator
|
|
43
|
+
@application_paginator ||= ModuleUtils.try_to superclass, :application_paginator
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Model paginator for current modal class. It comes from:
|
|
48
|
+
#
|
|
49
|
+
# - controller configuration {Wallaby::Paginatable::ClassMethods#model_paginator .model_paginator}
|
|
50
|
+
# - a generic paginator based on {Wallaby::Paginatable::ClassMethods#application_paginator .application_paginator}
|
|
51
|
+
# @return [Class] model paginator class
|
|
52
|
+
def current_paginator
|
|
53
|
+
@current_paginator ||=
|
|
54
|
+
(controller_to_get(:model_paginator) \
|
|
55
|
+
|| Map.paginator_map(current_model_class, controller_to_get(:application_paginator))).try do |klass|
|
|
56
|
+
Rails.logger.info %( - Current paginator: #{klass})
|
|
57
|
+
klass.new current_model_class, collection, params
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# To paginate the collection but only when either `page` or `per` param is given,
|
|
62
|
+
# or HTML response is requested
|
|
63
|
+
# @param query [#each]
|
|
64
|
+
# @param options [Hash]
|
|
65
|
+
# @option options [Boolean] :paginate whether collection should be paginated
|
|
66
|
+
# @return [#each]
|
|
67
|
+
# @see Wallaby::ModelServicer#paginate
|
|
68
|
+
def paginate(query, options)
|
|
69
|
+
options[:paginate] ? current_servicer.paginate(query, params) : query
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# This is a collection of the helper methods that overrides the rails methods
|
|
5
|
+
module RailsOverriddenMethods
|
|
6
|
+
protected
|
|
7
|
+
|
|
8
|
+
# Override {https://github.com/rails/rails/blob/master/actionview/lib/action_view/view_paths.rb
|
|
9
|
+
# ActionView::ViewPaths::ClassMethods#_prefixes} to extend the prefixes for **ActionView::ViewPaths** to look up
|
|
10
|
+
# in below precedence from high to low:
|
|
11
|
+
#
|
|
12
|
+
# - :mounted_path/:resources_name/:action_prefix (e.g. `admin/products/index`)
|
|
13
|
+
# - :mounted_path/:resources_name (e.g. `admin/products`)
|
|
14
|
+
# - :controller_path/:action_prefix
|
|
15
|
+
# - :controller_path
|
|
16
|
+
# - :parent_controller_path/:action_prefix
|
|
17
|
+
# - :parent_controller_path
|
|
18
|
+
# - :more_parent_controller_path/:action_prefix
|
|
19
|
+
# - :more_parent_controller_path
|
|
20
|
+
# - :theme_name/:action_prefix
|
|
21
|
+
# - :theme_name
|
|
22
|
+
# - wallaby/resources/:action_prefix
|
|
23
|
+
# - wallaby/resources
|
|
24
|
+
# @return [Array<String>]
|
|
25
|
+
def _prefixes
|
|
26
|
+
@_prefixes ||= PrefixesBuilder.build(
|
|
27
|
+
origin_prefixes: super,
|
|
28
|
+
theme_name: current_theme_name,
|
|
29
|
+
resources_name: current_resources_name,
|
|
30
|
+
script_name: request.env[SCRIPT_NAME],
|
|
31
|
+
action_name: params[:action]
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Override to provide support for cell lookup
|
|
36
|
+
# @return [Wallaby::CustomLookupContext]
|
|
37
|
+
def lookup_context
|
|
38
|
+
@_lookup_context ||= # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
39
|
+
CustomLookupContext.normalize(super, prefixes: _prefixes)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# Resources related attributes
|
|
5
|
+
module Resourcable
|
|
6
|
+
# Configurable attribute
|
|
7
|
+
module ClassMethods
|
|
8
|
+
# @!attribute [w] model_class
|
|
9
|
+
attr_writer :model_class
|
|
10
|
+
|
|
11
|
+
# @!attribute [r] model_class
|
|
12
|
+
# This attribute will be used by the dynamic router to find out which
|
|
13
|
+
# controller to dispatch to. For example:
|
|
14
|
+
#
|
|
15
|
+
# `/admin/products` will be dispatched to the controller that has the
|
|
16
|
+
# model class `Product`.
|
|
17
|
+
# @return [Class] the model class for controller.
|
|
18
|
+
# @example It can be customized as below:
|
|
19
|
+
# ```
|
|
20
|
+
# self.model_class = Product
|
|
21
|
+
# ```
|
|
22
|
+
# Or
|
|
23
|
+
# ```
|
|
24
|
+
# def self.model_class; Product; end
|
|
25
|
+
# ```
|
|
26
|
+
# @example To set model paginator
|
|
27
|
+
# class Admin::ProductionsController < Admin::ApplicationController
|
|
28
|
+
# self.model_class = ProductResources
|
|
29
|
+
# end
|
|
30
|
+
# @return [Class] model paginator
|
|
31
|
+
# @raise [ArgumentError] when **model_class** doesn't inherit from **application_paginator**
|
|
32
|
+
# @see Wallaby::ModelResources
|
|
33
|
+
def model_class
|
|
34
|
+
return unless self < ResourcesController
|
|
35
|
+
return if base_class? || self == Wallaby.configuration.mapping.resources_controller
|
|
36
|
+
|
|
37
|
+
@model_class ||= Map.model_class_map(name.gsub(/(^#{namespace}::)|(Controller$)/, EMPTY_STRING))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [String] resources name for current request
|
|
42
|
+
def current_resources_name
|
|
43
|
+
@current_resources_name ||= params[:resources]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @return [Class] model class for current request
|
|
47
|
+
def current_model_class
|
|
48
|
+
@current_model_class ||=
|
|
49
|
+
controller_to_get(__callee__, :model_class) || Map.model_class_map(current_resources_name || controller_path)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Shorthand of params[:id]
|
|
53
|
+
# @return [String, nil] ID param
|
|
54
|
+
def resource_id
|
|
55
|
+
params[:id]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @note This is a template method that can be overridden by subclasses.
|
|
59
|
+
# This is a method to return collection for index page.
|
|
60
|
+
#
|
|
61
|
+
# It can be customized as below in subclasses:
|
|
62
|
+
#
|
|
63
|
+
# ```
|
|
64
|
+
# def collection
|
|
65
|
+
# # do something before the origin action
|
|
66
|
+
# options = {} # NOTE: see `options` parameter for more details
|
|
67
|
+
# collection! options do |query| # NOTE: this is better than using `super`
|
|
68
|
+
# # NOTE: make sure a collection is returned
|
|
69
|
+
# query.where(active: true)
|
|
70
|
+
# end
|
|
71
|
+
# end
|
|
72
|
+
# ```
|
|
73
|
+
#
|
|
74
|
+
# Otherwise, it can be replaced completely in subclasses:
|
|
75
|
+
#
|
|
76
|
+
# ```
|
|
77
|
+
# def collection
|
|
78
|
+
# # NOTE: pagination should happen here if needed
|
|
79
|
+
# # NOTE: make sure `@collection` and conditional assignment (the OR EQUAL) operator are used
|
|
80
|
+
# @collection ||= paginate Product.active
|
|
81
|
+
# end
|
|
82
|
+
# ```
|
|
83
|
+
# @param options [Hash] (since 5.2.0)
|
|
84
|
+
# @option options [ActionController::Parameters, Hash] :params parameters for collection query
|
|
85
|
+
# @option options [Boolean] :paginate see {Wallaby::Paginatable#paginate}
|
|
86
|
+
# @yield [collection] (since 5.2.0) a block to run to extend collection, e.g. call chain with more queries
|
|
87
|
+
# @return [#each] a collection of records
|
|
88
|
+
def collection(options = {}, &block)
|
|
89
|
+
@collection ||=
|
|
90
|
+
ModuleUtils.yield_for(
|
|
91
|
+
begin
|
|
92
|
+
options[:paginate] = true unless options.key?(:paginate)
|
|
93
|
+
options[:params] ||= params
|
|
94
|
+
paginate current_servicer.collection(options.delete(:params)), options
|
|
95
|
+
end,
|
|
96
|
+
&block
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @note This is a template method that can be overridden by subclasses.
|
|
101
|
+
# This is a method to return resource for pages except `index`.
|
|
102
|
+
#
|
|
103
|
+
# `WARN: It does not do mass assignment since 5.2.0.`
|
|
104
|
+
#
|
|
105
|
+
# It can be customized as below in subclasses:
|
|
106
|
+
#
|
|
107
|
+
# ```
|
|
108
|
+
# def resource
|
|
109
|
+
# # do something before the origin action
|
|
110
|
+
# options = {} # NOTE: see `options` parameter for more details
|
|
111
|
+
# resource! options do |object| # NOTE: this is better than using `super`
|
|
112
|
+
# object.preload_status_from_api
|
|
113
|
+
# # NOTE: make sure object is returned
|
|
114
|
+
# object
|
|
115
|
+
# end
|
|
116
|
+
# end
|
|
117
|
+
# ```
|
|
118
|
+
#
|
|
119
|
+
# Otherwise, it can be replaced completely in subclasses:
|
|
120
|
+
#
|
|
121
|
+
# ```
|
|
122
|
+
# def resource
|
|
123
|
+
# # NOTE: make sure `@resource` and conditional assignment (the OR EQUAL) operator are used
|
|
124
|
+
# @resource ||= resource_id.present? ? Product.find_by_slug(resource_id) : Product.new(arrival: true)
|
|
125
|
+
# end
|
|
126
|
+
# ```
|
|
127
|
+
# @param options [Hash] (since 5.2.0)
|
|
128
|
+
# @option options [Array<String>] :non_find_actions action names that shouldn't use resource find.
|
|
129
|
+
# (Default to `%w(index new create)`)
|
|
130
|
+
# @option options [ActionController::Parameters, Hash] :find_params parameters/options for resource finding
|
|
131
|
+
# @option options [ActionController::Parameters, Hash] :new_params parameters/options for new resource
|
|
132
|
+
# @yield [resource] (since 5.2.0) a block to run to extend resource, e.g. making change to the resource.
|
|
133
|
+
# Please make sure to return the resource at the end of block
|
|
134
|
+
# @return [Object] either persisted or unpersisted resource instance
|
|
135
|
+
# @raise [ResourceNotFound] if resource is nil
|
|
136
|
+
def resource(options = {}, &block)
|
|
137
|
+
@resource ||=
|
|
138
|
+
ModuleUtils.yield_for(
|
|
139
|
+
# this will testify both resource and resources
|
|
140
|
+
if resource_id.present? || !(options[:non_find_actions] || NON_FIND_ACTIONS).include?(action_name)
|
|
141
|
+
current_servicer.find resource_id, options[:find_params]
|
|
142
|
+
else
|
|
143
|
+
current_servicer.new options[:new_params]
|
|
144
|
+
end,
|
|
145
|
+
&block
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|