wallaby-core 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/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
|