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,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
# This is the controller with only authentication logics.
|
|
5
|
+
class SecureController < ::Wallaby::ApplicationController
|
|
6
|
+
helper SecureHelper
|
|
7
|
+
helper_method :current_user
|
|
8
|
+
|
|
9
|
+
rescue_from NotAuthenticated, with: :unauthorized
|
|
10
|
+
rescue_from Forbidden, with: :forbidden
|
|
11
|
+
|
|
12
|
+
# Unauthorized page.
|
|
13
|
+
# @param exception [Exception] exception comes from `rescue_from`
|
|
14
|
+
def unauthorized(exception = nil)
|
|
15
|
+
error_rendering exception, __callee__
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Forbidden page.
|
|
19
|
+
# @param exception [Exception] exception comes from `rescue_from`
|
|
20
|
+
def forbidden(exception = nil)
|
|
21
|
+
error_rendering exception, __callee__
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @note This is a template method that can be overridden by subclasses
|
|
25
|
+
# This {current_user} method will try to looking up the actual implementation from the following
|
|
26
|
+
# places from high precedence to low:
|
|
27
|
+
#
|
|
28
|
+
# - {Wallaby::Configuration::Security#current_user}
|
|
29
|
+
# - `super`
|
|
30
|
+
# - do nothing
|
|
31
|
+
#
|
|
32
|
+
# It can be replaced completely in subclasses:
|
|
33
|
+
#
|
|
34
|
+
# ```
|
|
35
|
+
# def current_user
|
|
36
|
+
# # NOTE: please ensure `@current_user` is assigned, for instance:
|
|
37
|
+
# @current_user ||= User.new params.slice(:email)
|
|
38
|
+
# end
|
|
39
|
+
# ```
|
|
40
|
+
# @return [Object] a user object
|
|
41
|
+
def current_user
|
|
42
|
+
@current_user ||=
|
|
43
|
+
if security.current_user? || !defined? super
|
|
44
|
+
instance_exec(&security.current_user)
|
|
45
|
+
else
|
|
46
|
+
super
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @note This is a template method that can be overridden by subclasses
|
|
51
|
+
# This {authenticate_user!} method will try to looking up the actual implementation from the following
|
|
52
|
+
# places from high precedence to low:
|
|
53
|
+
#
|
|
54
|
+
# - {Wallaby::Configuration::Security#authenticate}
|
|
55
|
+
# - `super`
|
|
56
|
+
# - do nothing
|
|
57
|
+
#
|
|
58
|
+
# It can be replaced completely in subclasses:
|
|
59
|
+
#
|
|
60
|
+
# ```
|
|
61
|
+
# def authenticate_user!
|
|
62
|
+
# authenticate_or_request_with_http_basic do |username, password|
|
|
63
|
+
# username == 'too_simple' && password == 'too_naive'
|
|
64
|
+
# end
|
|
65
|
+
# end
|
|
66
|
+
# ```
|
|
67
|
+
# @return [true] when user is authenticated successfully
|
|
68
|
+
# @raise [Wallaby::NotAuthenticated] when user fails to authenticate
|
|
69
|
+
def authenticate_user!
|
|
70
|
+
authenticated =
|
|
71
|
+
if security.authenticate? || !defined? super
|
|
72
|
+
instance_exec(&security.authenticate)
|
|
73
|
+
else
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
raise NotAuthenticated unless authenticated
|
|
77
|
+
|
|
78
|
+
true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @!visibility private
|
|
4
|
+
# Defualt ability for wallaby
|
|
5
|
+
# If main app has defined `ability.rb`, this file will not be loaded/used.
|
|
6
|
+
class Ability
|
|
7
|
+
include ::CanCan::Ability
|
|
8
|
+
|
|
9
|
+
# @param _user [Object]
|
|
10
|
+
def initialize(_user)
|
|
11
|
+
can :manage, :all
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
|
3
|
+
# than English, add the necessary files in this directory.
|
|
4
|
+
#
|
|
5
|
+
# To use the locales, use `I18n.t`:
|
|
6
|
+
#
|
|
7
|
+
# I18n.t 'hello'
|
|
8
|
+
#
|
|
9
|
+
# In views, this is aliased to just `t`:
|
|
10
|
+
#
|
|
11
|
+
# <%= t('hello') %>
|
|
12
|
+
#
|
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
|
14
|
+
#
|
|
15
|
+
# I18n.locale = :es
|
|
16
|
+
#
|
|
17
|
+
# This would use the information in config/locales/es.yml.
|
|
18
|
+
#
|
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
|
21
|
+
|
|
22
|
+
en:
|
|
23
|
+
labels:
|
|
24
|
+
count: 'Count: '
|
|
25
|
+
auto_select_hint: 'Type to select...'
|
|
26
|
+
upload: 'Upload'
|
|
27
|
+
empty: 'null'
|
|
28
|
+
na: 'n/a'
|
|
29
|
+
edit: 'Edit # %{id}'
|
|
30
|
+
create: 'Create a %{model}'
|
|
31
|
+
|
|
32
|
+
buttons:
|
|
33
|
+
save: 'Save'
|
|
34
|
+
|
|
35
|
+
links:
|
|
36
|
+
new: 'Create %{model}'
|
|
37
|
+
show: 'Show'
|
|
38
|
+
edit: 'Edit'
|
|
39
|
+
delete: 'Delete'
|
|
40
|
+
cancel: 'Cancel'
|
|
41
|
+
confirm:
|
|
42
|
+
delete: 'Please confirm to delete'
|
|
43
|
+
export: 'Export as %{ext}'
|
|
44
|
+
|
|
45
|
+
http_errors:
|
|
46
|
+
report_error_html: 'And report the error <a href="https://github.com/reinteractive/wallaby/issues/new" target="_blank">here</a>.'
|
|
47
|
+
not_implemented: 'Not implemented.'
|
|
48
|
+
internal_server_error: 'Hope you feel better.'
|
|
49
|
+
bad_request: 'Your request is not supported.'
|
|
50
|
+
not_found: 'Not found.'
|
|
51
|
+
unprocessable_entity: 'Your request cannot be processed.'
|
|
52
|
+
unauthorized: 'You need to sign in to access this page.'
|
|
53
|
+
forbidden: 'You need permission to access this page.'
|
|
54
|
+
|
|
55
|
+
json_errors:
|
|
56
|
+
not_implemented: 'Not implemented.'
|
|
57
|
+
internal_server_error: 'Internal server error.'
|
|
58
|
+
bad_request: 'Your request is not supported.'
|
|
59
|
+
not_found: 'Not found.'
|
|
60
|
+
unprocessable_entity: 'Your request cannot be processed.'
|
|
61
|
+
unauthorized: 'You need to sign in to access this page.'
|
|
62
|
+
forbidden: 'You need permission to access this page.'
|
|
63
|
+
|
|
64
|
+
errors:
|
|
65
|
+
invalid:
|
|
66
|
+
models: '%{models} are invalid models.'
|
|
67
|
+
inheritance: '%{klass} does not inherit from %{parent}.'
|
|
68
|
+
type_required: 'Type is required for %{field_name}.'
|
|
69
|
+
not_found:
|
|
70
|
+
collection: 'Records cannot be found. Click + button to add one.'
|
|
71
|
+
model: 'Model %{model} cannot be found.'
|
|
72
|
+
resource: 'Record %{resource} cannot be found.'
|
|
73
|
+
unprocessable_entity:
|
|
74
|
+
keyword_search: 'Unable to perform keyword search when no text fields can be used.'
|
|
75
|
+
field_colon_search: 'Unable to perform field colon search for %{invalid_fields}.'
|
|
76
|
+
model: 'Unable to handle model %{model}.'
|
|
77
|
+
unauthorized: 'User %{user} is trying to perform %{action} on %{subject}'
|
|
78
|
+
pundit:
|
|
79
|
+
not_found:
|
|
80
|
+
scope_policy: 'Cannot find scope policy for %{scope}.'
|
|
81
|
+
attributes_for: 'Cannot find attributes for %{subject}.'
|
|
82
|
+
activerecord:
|
|
83
|
+
paginatable: '%{collection} is not paginatable.'
|
|
84
|
+
required: '%{subject} is required.'
|
|
85
|
+
not_implemented:
|
|
86
|
+
model_servicer: 'Custom model servicer method `%{method_name}` is not implemented'
|
|
87
|
+
|
|
88
|
+
pagination:
|
|
89
|
+
prev: 'Prev'
|
|
90
|
+
next: 'Next'
|
|
91
|
+
from_to: '%{from} to %{to}'
|
|
92
|
+
of: ' of '
|
|
93
|
+
total_count: '%{total}'
|
|
94
|
+
pers: 'Page Size'
|
|
95
|
+
pages: 'Page Number'
|
|
96
|
+
|
|
97
|
+
filters:
|
|
98
|
+
title: 'Filters'
|
|
99
|
+
all: 'All'
|
|
100
|
+
|
|
101
|
+
search:
|
|
102
|
+
hint: 'Press enter to search.'
|
|
103
|
+
|
|
104
|
+
hints:
|
|
105
|
+
box_html: 'Format: <code>(x1, y1), (x2, y2)</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are any two opposite corners of the box.'
|
|
106
|
+
cidr_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
|
|
107
|
+
circle_html: 'Format: <code><(x, y), r></code> where <i>(x,y)</i> is the center point and <i>r</i> is the radius of the circle.'
|
|
108
|
+
hstore_html: 'Format: <code>"Key1" => "Value1", "Key2" => "Value2"</code> is used for input and output, includes zero or more <i>key => value</i> pairs separated by commas.'
|
|
109
|
+
inet_html: 'Example: <code>192.168.1.1/24</code> which holds an IPv4 or IPv6 network specification.'
|
|
110
|
+
line_html: 'Format: <code>{ A, B, C }</code> which are represented by the linear equation <i>Ax + By + C = 0</i>.'
|
|
111
|
+
lseg_html: 'Format: <code>[(x1, y1), (x2, y2)]</code> where <i>(x1,y1)</i> and <i>(x2,y2)</i> are the end points of the line segment.'
|
|
112
|
+
ltree_html: 'Example: <code>Top.Countries.Europe.Russia</code> which is a sequence of zero or more labels separated by dots.'
|
|
113
|
+
macaddr_html: 'Example: <code>08:00:2b:01:02:03</code> which stores MAC addresses.'
|
|
114
|
+
path_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the path.'
|
|
115
|
+
polygon_html: 'Format: <code>((x1, y1) , ... , (xn, yn))</code> where the points are the end points of the line segments comprising the boundary of the polygon.'
|
|
116
|
+
|
|
117
|
+
deprecation:
|
|
118
|
+
authorizer: "[DEPRECATION] `authorizer` will be removed from 5.3.*. Please use `current_authorizer` instead.\n(called from %{from})"
|
|
119
|
+
current_model_service: "[DEPRECATION] `current_model_service` will be removed from 5.3.*. Please use `current_servicer` instead.\n(called from %{from})"
|
|
120
|
+
find_filter_name: "[DEPRECATION] `Wallaby::Utils.find_filter_name` will be removed from 5.3.*. Please use `Wallaby::FilterUtils.filter_name_by` instead.\n(called from %{from})"
|
|
121
|
+
form_type_partial_render: "[DEPRECATION] `form_type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
|
|
122
|
+
index_params: "[DEPRECATION] `index_params` will be removed from 5.3.*.\n(called from %{from})"
|
|
123
|
+
paginator_of: "[DEPRECATION] `paginator_of` will be removed from 5.3.*. Please use `current_paginator` instead.\n(called from %{from})"
|
|
124
|
+
resource_paginator_inheirtance: "[DEPRECATION] `Wallaby::ResourcePaginator` will be removed from 5.3.*. Please inherit from `Wallaby::ModelPaginator` instead.\n(called from %{from})"
|
|
125
|
+
resource_paginator=: "[DEPRECATION] `resource_paginator=` will be removed from 5.3.*. Please use `model_paginator=` instead.\n(called from %{from})"
|
|
126
|
+
type_partial_render: "[DEPRECATION] `type_partial_render` will be removed from 5.3.*. Please use `type_render` instead.\n(called from %{from})"
|
|
127
|
+
|
|
128
|
+
fa:
|
|
129
|
+
# map fa 5's icon name to version 4
|
|
130
|
+
# @see this fa migration document https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4
|
|
131
|
+
v4:
|
|
132
|
+
clock: 'clock-o'
|
|
133
|
+
bars: 'navicon'
|
|
134
|
+
calendar: 'calendar-o'
|
|
135
|
+
check-square: 'check-square-o'
|
|
136
|
+
square: 'square-o'
|
|
137
|
+
link: 'chain'
|
|
138
|
+
user: 'user-o'
|
|
139
|
+
v5:
|
|
140
|
+
no-need: 'no-need'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
|
3
|
+
# than English, add the necessary files in this directory.
|
|
4
|
+
#
|
|
5
|
+
# To use the locales, use `I18n.t`:
|
|
6
|
+
#
|
|
7
|
+
# I18n.t 'hello'
|
|
8
|
+
#
|
|
9
|
+
# In views, this is aliased to just `t`:
|
|
10
|
+
#
|
|
11
|
+
# <%= t('hello') %>
|
|
12
|
+
#
|
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
|
14
|
+
#
|
|
15
|
+
# I18n.locale = :es
|
|
16
|
+
#
|
|
17
|
+
# This would use the information in config/locales/es.yml.
|
|
18
|
+
#
|
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
|
21
|
+
|
|
22
|
+
en:
|
|
23
|
+
wallaby:
|
|
24
|
+
map:
|
|
25
|
+
missing_mode_for_model_class: "[WALLABY] Don't know how to handle this model %{model}."
|
|
26
|
+
model_class_mapper:
|
|
27
|
+
missing_model_class: "[WALLABY] Please define self.model_class for %{model} or set it as global.\n @see Wallaby.configuration.mapping"
|
|
28
|
+
|
|
29
|
+
mode:
|
|
30
|
+
inherit_required: '%{klass} must inherit from %{parent}.'
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Wallaby::Engine.routes.draw do
|
|
4
|
+
# NOTE: For health check if needed
|
|
5
|
+
# @see Wallaby::ApplicationController#healthy
|
|
6
|
+
get 'status', to: 'wallaby/resources#healthy'
|
|
7
|
+
|
|
8
|
+
with_options to: Wallaby::ResourcesRouter.new do |route|
|
|
9
|
+
# @see `home` action for more
|
|
10
|
+
route.root defaults: { action: 'home' }
|
|
11
|
+
|
|
12
|
+
# To generate error pages for all supported HTTP status
|
|
13
|
+
Wallaby::ERRORS.each do |status|
|
|
14
|
+
code = Rack::Utils::SYMBOL_TO_STATUS_CODE[status]
|
|
15
|
+
route.get status, defaults: { action: status }
|
|
16
|
+
route.get code.to_s, defaults: { action: status }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# To generate general CRUD resourceful routes
|
|
20
|
+
# @see Wallaby::ResourcesRouter
|
|
21
|
+
scope path: ':resources' do
|
|
22
|
+
# @see Wallaby::ResourcesController#index
|
|
23
|
+
route.get '', defaults: { action: 'index' }, as: :resources
|
|
24
|
+
# @see Wallaby::ResourcesController#new
|
|
25
|
+
route.get 'new', defaults: { action: 'new' }, as: :new_resource
|
|
26
|
+
# @see Wallaby::ResourcesController#edit
|
|
27
|
+
route.get ':id/edit', defaults: { action: 'edit' }, as: :edit_resource
|
|
28
|
+
# @see Wallaby::ResourcesController#show
|
|
29
|
+
route.get ':id', defaults: { action: 'show' }, as: :resource
|
|
30
|
+
|
|
31
|
+
# @see Wallaby::ResourcesController#create
|
|
32
|
+
route.post '', defaults: { action: 'create' }
|
|
33
|
+
# @see Wallaby::ResourcesController#update
|
|
34
|
+
route.match ':id', via: %i(patch put), defaults: { action: 'update' }
|
|
35
|
+
# @see Wallaby::ResourcesController#destroy
|
|
36
|
+
route.delete ':id', defaults: { action: 'destroy' }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
class Custom
|
|
5
|
+
# Custom modal decorator
|
|
6
|
+
class ModelDecorator < ::Wallaby::ModelDecorator
|
|
7
|
+
# Assume that attributes come from the setter/getter, e.g. `name=`/`name`
|
|
8
|
+
# @return [ActiveSupport::HashWithIndifferentAccess] metadata
|
|
9
|
+
def fields
|
|
10
|
+
@fields ||=
|
|
11
|
+
::ActiveSupport::HashWithIndifferentAccess.new.tap do |hash|
|
|
12
|
+
methods = model_class.public_instance_methods(false).map(&:to_s)
|
|
13
|
+
methods
|
|
14
|
+
.grep(/[^=]$/)
|
|
15
|
+
.select { |method_id| methods.include? "#{method_id}=" }
|
|
16
|
+
.each { |attribute| hash[attribute] = { label: attribute.humanize, type: 'string' } }
|
|
17
|
+
end.freeze
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# A copy of {#fields} for index page
|
|
21
|
+
# @return [ActiveSupport::HashWithIndifferentAccess] metadata
|
|
22
|
+
def index_fields
|
|
23
|
+
@index_fields ||= Utils.clone fields
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# A copy of {#fields} for show page
|
|
27
|
+
# @return [ActiveSupport::HashWithIndifferentAccess] metadata
|
|
28
|
+
def show_fields
|
|
29
|
+
@show_fields ||= Utils.clone fields
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# A copy of {#fields} for form (new/edit) page
|
|
33
|
+
# @return [ActiveSupport::HashWithIndifferentAccess] metadata
|
|
34
|
+
def form_fields
|
|
35
|
+
@form_fields ||= Utils.clone fields
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Array<String>] a list of field names for index page
|
|
39
|
+
def index_field_names
|
|
40
|
+
@index_field_names ||= reposition index_fields.keys, primary_key
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Array<String>] a list of field names for show page
|
|
44
|
+
def show_field_names
|
|
45
|
+
@show_field_names ||= reposition show_fields.keys, primary_key
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Array<String>] a list of field names for form (new/edit) page
|
|
49
|
+
def form_field_names
|
|
50
|
+
@form_field_names ||= form_fields.keys - [primary_key.to_s]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [ActiveModel::Errors]
|
|
54
|
+
def form_active_errors(resource)
|
|
55
|
+
@form_active_errors ||= ActiveModel::Errors.new resource
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @return [String, Symbole] primary key name
|
|
59
|
+
def primary_key
|
|
60
|
+
@primary_key ||= :id
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @param resource [Object]
|
|
64
|
+
# @return [String]
|
|
65
|
+
def guess_title(resource)
|
|
66
|
+
field_name = FieldUtils.first_field_by({ name: /name|title|subject/ }, fields)
|
|
67
|
+
ModuleUtils.try_to resource, field_name
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
class Custom
|
|
5
|
+
# Model finder
|
|
6
|
+
class ModelFinder < ::Wallaby::ModelFinder
|
|
7
|
+
# @return [Array<Class>] a list of classes
|
|
8
|
+
def all
|
|
9
|
+
Wallaby.configuration.custom_models.presence
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
class Custom
|
|
5
|
+
# Model pagination provider
|
|
6
|
+
class ModelPaginationProvider < ::Wallaby::ModelPaginationProvider
|
|
7
|
+
# By default, it doesn't support pagination
|
|
8
|
+
# @return [false]
|
|
9
|
+
def paginatable?
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wallaby
|
|
4
|
+
class Custom
|
|
5
|
+
# Model service provider
|
|
6
|
+
class ModelServiceProvider < ::Wallaby::ModelServiceProvider
|
|
7
|
+
# @raise [Wallaby::NotImplemented]
|
|
8
|
+
def permit(*)
|
|
9
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @raise [Wallaby::NotImplemented]
|
|
13
|
+
def collection(*)
|
|
14
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @raise [Wallaby::NotImplemented]
|
|
18
|
+
def paginate(*)
|
|
19
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @raise [Wallaby::NotImplemented]
|
|
23
|
+
def new(*)
|
|
24
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @raise [Wallaby::NotImplemented]
|
|
28
|
+
def find(*)
|
|
29
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @raise [Wallaby::NotImplemented]
|
|
33
|
+
def create(*)
|
|
34
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @raise [Wallaby::NotImplemented]
|
|
38
|
+
def update(*)
|
|
39
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @raise [Wallaby::NotImplemented]
|
|
43
|
+
def destroy(*)
|
|
44
|
+
raise Wallaby::NotImplemented, I18n.t('errors.not_implemented.model_servicer', method_name: __callee__)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|