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.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +31 -0
  4. data/app/controllers/wallaby/application_controller.rb +84 -0
  5. data/app/controllers/wallaby/resources_controller.rb +381 -0
  6. data/app/controllers/wallaby/secure_controller.rb +81 -0
  7. data/app/security/ability.rb +13 -0
  8. data/config/locales/wallaby.en.yml +140 -0
  9. data/config/locales/wallaby_class.en.yml +30 -0
  10. data/config/routes.rb +39 -0
  11. data/lib/adaptors/wallaby/custom.rb +7 -0
  12. data/lib/adaptors/wallaby/custom/default_provider.rb +9 -0
  13. data/lib/adaptors/wallaby/custom/model_decorator.rb +71 -0
  14. data/lib/adaptors/wallaby/custom/model_finder.rb +13 -0
  15. data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +14 -0
  16. data/lib/adaptors/wallaby/custom/model_service_provider.rb +48 -0
  17. data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +72 -0
  18. data/lib/authorizers/wallaby/default_authorization_provider.rb +58 -0
  19. data/lib/authorizers/wallaby/model_authorizer.rb +100 -0
  20. data/lib/authorizers/wallaby/pundit_authorization_provider.rb +89 -0
  21. data/lib/concerns/wallaby/authorizable.rb +103 -0
  22. data/lib/concerns/wallaby/baseable.rb +36 -0
  23. data/lib/concerns/wallaby/decoratable.rb +101 -0
  24. data/lib/concerns/wallaby/defaultable.rb +38 -0
  25. data/lib/concerns/wallaby/engineable.rb +61 -0
  26. data/lib/concerns/wallaby/fieldable.rb +78 -0
  27. data/lib/concerns/wallaby/paginatable.rb +72 -0
  28. data/lib/concerns/wallaby/rails_overridden_methods.rb +42 -0
  29. data/lib/concerns/wallaby/resourcable.rb +149 -0
  30. data/lib/concerns/wallaby/servicable.rb +68 -0
  31. data/lib/concerns/wallaby/shared_helpers.rb +22 -0
  32. data/lib/concerns/wallaby/themeable.rb +40 -0
  33. data/lib/decorators/wallaby/resource_decorator.rb +189 -0
  34. data/lib/errors/wallaby/cell_handling.rb +6 -0
  35. data/lib/errors/wallaby/forbidden.rb +6 -0
  36. data/lib/errors/wallaby/general_error.rb +6 -0
  37. data/lib/errors/wallaby/invalid_error.rb +6 -0
  38. data/lib/errors/wallaby/model_not_found.rb +11 -0
  39. data/lib/errors/wallaby/not_authenticated.rb +6 -0
  40. data/lib/errors/wallaby/not_found.rb +6 -0
  41. data/lib/errors/wallaby/not_implemented.rb +6 -0
  42. data/lib/errors/wallaby/resource_not_found.rb +11 -0
  43. data/lib/errors/wallaby/unprocessable_entity.rb +6 -0
  44. data/lib/forms/wallaby/form_builder.rb +60 -0
  45. data/lib/helpers/wallaby/application_helper.rb +79 -0
  46. data/lib/helpers/wallaby/base_helper.rb +65 -0
  47. data/lib/helpers/wallaby/configuration_helper.rb +18 -0
  48. data/lib/helpers/wallaby/form_helper.rb +62 -0
  49. data/lib/helpers/wallaby/index_helper.rb +84 -0
  50. data/lib/helpers/wallaby/links_helper.rb +213 -0
  51. data/lib/helpers/wallaby/resources_helper.rb +52 -0
  52. data/lib/helpers/wallaby/secure_helper.rb +54 -0
  53. data/lib/helpers/wallaby/styling_helper.rb +82 -0
  54. data/lib/interfaces/wallaby/mode.rb +72 -0
  55. data/lib/interfaces/wallaby/model_authorization_provider.rb +99 -0
  56. data/lib/interfaces/wallaby/model_decorator.rb +168 -0
  57. data/lib/interfaces/wallaby/model_finder.rb +12 -0
  58. data/lib/interfaces/wallaby/model_pagination_provider.rb +107 -0
  59. data/lib/interfaces/wallaby/model_service_provider.rb +84 -0
  60. data/lib/paginators/wallaby/model_paginator.rb +115 -0
  61. data/lib/paginators/wallaby/resource_paginator.rb +12 -0
  62. data/lib/parsers/wallaby/parser.rb +34 -0
  63. data/lib/renderers/wallaby/cell.rb +137 -0
  64. data/lib/renderers/wallaby/cell_resolver.rb +89 -0
  65. data/lib/renderers/wallaby/custom_lookup_context.rb +64 -0
  66. data/lib/renderers/wallaby/custom_partial_renderer.rb +33 -0
  67. data/lib/renderers/wallaby/custom_renderer.rb +16 -0
  68. data/lib/responders/wallaby/json_api_responder.rb +101 -0
  69. data/lib/responders/wallaby/resources_responder.rb +28 -0
  70. data/lib/routes/wallaby/resources_router.rb +72 -0
  71. data/lib/servicers/wallaby/model_servicer.rb +154 -0
  72. data/lib/services/wallaby/engine_name_finder.rb +22 -0
  73. data/lib/services/wallaby/engine_url_for.rb +46 -0
  74. data/lib/services/wallaby/link_options_normalizer.rb +19 -0
  75. data/lib/services/wallaby/map/mode_mapper.rb +27 -0
  76. data/lib/services/wallaby/map/model_class_collector.rb +49 -0
  77. data/lib/services/wallaby/map/model_class_mapper.rb +38 -0
  78. data/lib/services/wallaby/prefixes_builder.rb +66 -0
  79. data/lib/services/wallaby/sorting/hash_builder.rb +19 -0
  80. data/lib/services/wallaby/sorting/link_builder.rb +69 -0
  81. data/lib/services/wallaby/sorting/next_builder.rb +63 -0
  82. data/lib/services/wallaby/sorting/single_builder.rb +20 -0
  83. data/lib/services/wallaby/type_renderer.rb +50 -0
  84. data/lib/support/action_dispatch/routing/mapper.rb +75 -0
  85. data/lib/tree/wallaby/node.rb +25 -0
  86. data/lib/utils/wallaby/cell_utils.rb +34 -0
  87. data/lib/utils/wallaby/field_utils.rb +43 -0
  88. data/lib/utils/wallaby/filter_utils.rb +20 -0
  89. data/lib/utils/wallaby/model_utils.rb +51 -0
  90. data/lib/utils/wallaby/module_utils.rb +46 -0
  91. data/lib/utils/wallaby/params_utils.rb +14 -0
  92. data/lib/utils/wallaby/preload_utils.rb +44 -0
  93. data/lib/utils/wallaby/test_utils.rb +34 -0
  94. data/lib/utils/wallaby/utils.rb +27 -0
  95. data/lib/wallaby/configuration.rb +103 -0
  96. data/lib/wallaby/configuration/features.rb +24 -0
  97. data/lib/wallaby/configuration/mapping.rb +140 -0
  98. data/lib/wallaby/configuration/metadata.rb +23 -0
  99. data/lib/wallaby/configuration/models.rb +46 -0
  100. data/lib/wallaby/configuration/pagination.rb +30 -0
  101. data/lib/wallaby/configuration/security.rb +98 -0
  102. data/lib/wallaby/configuration/sorting.rb +28 -0
  103. data/lib/wallaby/constants.rb +45 -0
  104. data/lib/wallaby/core.rb +117 -0
  105. data/lib/wallaby/core/version.rb +7 -0
  106. data/lib/wallaby/engine.rb +43 -0
  107. data/lib/wallaby/map.rb +170 -0
  108. 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}.'
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ # Custom mode
5
+ class Custom < Mode
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ class Custom
5
+ # Default provider for custom mode
6
+ class DefaultProvider < DefaultAuthorizationProvider
7
+ end
8
+ end
9
+ 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