wallaby-core 0.2.1 → 0.2.2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/controllers/wallaby/resources_controller.rb +10 -1
  4. data/config/locales/wallaby_class.en.yml +2 -2
  5. data/lib/adaptors/wallaby/custom/default_provider.rb +1 -1
  6. data/lib/adaptors/wallaby/custom/model_decorator.rb +8 -7
  7. data/lib/adaptors/wallaby/custom/model_finder.rb +3 -2
  8. data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +1 -1
  9. data/lib/adaptors/wallaby/custom/model_service_provider.rb +1 -40
  10. data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +29 -24
  11. data/lib/authorizers/wallaby/default_authorization_provider.rb +6 -13
  12. data/lib/authorizers/wallaby/model_authorizer.rb +43 -67
  13. data/lib/authorizers/wallaby/pundit_authorization_provider.rb +21 -30
  14. data/lib/concerns/wallaby/application_concern.rb +1 -2
  15. data/lib/concerns/wallaby/authentication_concern.rb +74 -5
  16. data/lib/concerns/wallaby/authorizable.rb +8 -8
  17. data/lib/concerns/wallaby/baseable.rb +91 -10
  18. data/lib/concerns/wallaby/decoratable.rb +3 -3
  19. data/lib/concerns/wallaby/engineable.rb +1 -1
  20. data/lib/concerns/wallaby/fieldable.rb +4 -4
  21. data/lib/concerns/wallaby/paginatable.rb +3 -3
  22. data/lib/concerns/wallaby/resourcable.rb +0 -35
  23. data/lib/concerns/wallaby/resources_concern.rb +3 -2
  24. data/lib/concerns/wallaby/servicable.rb +4 -4
  25. data/lib/decorators/wallaby/resource_decorator.rb +53 -80
  26. data/lib/errors/wallaby/class_not_found.rb +6 -0
  27. data/lib/errors/wallaby/model_not_found.rb +2 -0
  28. data/lib/helpers/wallaby/resources_helper.rb +3 -0
  29. data/lib/helpers/wallaby/secure_helper.rb +3 -3
  30. data/lib/interfaces/wallaby/mode.rb +3 -3
  31. data/lib/interfaces/wallaby/model_authorization_provider.rb +15 -13
  32. data/lib/interfaces/wallaby/model_decorator.rb +15 -3
  33. data/lib/paginators/wallaby/model_paginator.rb +14 -45
  34. data/lib/servicers/wallaby/model_servicer.rb +31 -62
  35. data/lib/services/wallaby/map/mode_mapper.rb +14 -14
  36. data/lib/services/wallaby/map/model_class_collector.rb +1 -1
  37. data/lib/services/wallaby/map/model_class_mapper.rb +7 -26
  38. data/lib/services/wallaby/type_renderer.rb +0 -10
  39. data/lib/utils/wallaby/model_utils.rb +4 -3
  40. data/lib/utils/wallaby/utils.rb +9 -8
  41. data/lib/wallaby/class_array.rb +75 -0
  42. data/lib/wallaby/class_hash.rb +94 -0
  43. data/lib/wallaby/classifier.rb +29 -0
  44. data/lib/wallaby/configuration.rb +31 -2
  45. data/lib/wallaby/configuration/mapping.rb +33 -21
  46. data/lib/wallaby/configuration/metadata.rb +1 -1
  47. data/lib/wallaby/configuration/models.rb +5 -9
  48. data/lib/wallaby/configuration/security.rb +6 -3
  49. data/lib/wallaby/configuration/sorting.rb +1 -1
  50. data/lib/wallaby/core.rb +13 -7
  51. data/lib/wallaby/core/version.rb +1 -1
  52. data/lib/wallaby/engine.rb +9 -20
  53. data/lib/wallaby/logger.rb +35 -0
  54. data/lib/wallaby/map.rb +20 -17
  55. data/lib/wallaby/preloader.rb +77 -0
  56. metadata +8 -4
  57. data/lib/utils/wallaby/logger.rb +0 -21
  58. data/lib/utils/wallaby/preload_utils.rb +0 -44
@@ -17,7 +17,7 @@ module Wallaby
17
17
  # self.engine_name = 'admin_engine'
18
18
  # end
19
19
  # @return [String, Symbol, nil] engine name
20
- # @since 5.2.0
20
+ # @since wallaby-5.2.0
21
21
  def engine_name
22
22
  @engine_name ||= ModuleUtils.try_to superclass, :engine_name
23
23
  end
@@ -18,7 +18,7 @@ module Wallaby
18
18
  # @param field_name [String, Symbol] field name
19
19
  # @return [String, Symbol] type for a given field
20
20
  def type_of(field_name)
21
- validate_presence_of field_name, metadata_of(field_name)[:type]
21
+ ensure_type_is_present field_name, metadata_of(field_name)[:type]
22
22
  end
23
23
 
24
24
  # @param field_name [String, Symbol] field name
@@ -36,7 +36,7 @@ module Wallaby
36
36
  # @param field_name [String, Symbol] field name
37
37
  # @return [String, Symbol] index type for a given field
38
38
  def index_type_of(field_name)
39
- validate_presence_of field_name, index_metadata_of(field_name)[:type]
39
+ ensure_type_is_present field_name, index_metadata_of(field_name)[:type], 'index_'
40
40
  end
41
41
 
42
42
  # @param field_name [String, Symbol] field name
@@ -54,7 +54,7 @@ module Wallaby
54
54
  # @param field_name [String, Symbol] field name
55
55
  # @return [String, Symbol] show type for a given field
56
56
  def show_type_of(field_name)
57
- validate_presence_of field_name, show_metadata_of(field_name)[:type]
57
+ ensure_type_is_present field_name, show_metadata_of(field_name)[:type], 'show_'
58
58
  end
59
59
 
60
60
  # @param field_name [String, Symbol] field name
@@ -72,7 +72,7 @@ module Wallaby
72
72
  # @param field_name [String, Symbol] field name
73
73
  # @return [String, Symbol] form type for a given field
74
74
  def form_type_of(field_name)
75
- validate_presence_of field_name, form_metadata_of(field_name)[:type]
75
+ ensure_type_is_present field_name, form_metadata_of(field_name)[:type], 'form_'
76
76
  end
77
77
  end
78
78
  end
@@ -20,7 +20,7 @@ module Wallaby
20
20
  # @return [Class] model paginator
21
21
  # @raise [ArgumentError] when **model_paginator** doesn't inherit from **application_paginator**
22
22
  # @see Wallaby::ModelPaginator
23
- # @since 5.2.0
23
+ # @since wallaby-5.2.0
24
24
  attr_reader :model_paginator
25
25
 
26
26
  # @!attribute [w] application_paginator
@@ -38,7 +38,7 @@ module Wallaby
38
38
  # @return [Class] application decorator
39
39
  # @raise [ArgumentError] when **model_paginator** doesn't inherit from **application_paginator**
40
40
  # @see Wallaby::ModelPaginator
41
- # @since 5.2.0
41
+ # @since wallaby-5.2.0
42
42
  def application_paginator
43
43
  @application_paginator ||= ModuleUtils.try_to superclass, :application_paginator
44
44
  end
@@ -53,7 +53,7 @@ module Wallaby
53
53
  @current_paginator ||=
54
54
  (controller_to_get(:model_paginator) \
55
55
  || Map.paginator_map(current_model_class, controller_to_get(:application_paginator))).try do |klass|
56
- Logger.debug %(Current paginator: #{klass})
56
+ Logger.debug %(Current paginator: #{klass}), sourcing: false
57
57
  klass.new current_model_class, collection, params
58
58
  end
59
59
  end
@@ -3,41 +3,6 @@
3
3
  module Wallaby
4
4
  # Resources related attributes
5
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
6
  # @return [String] resources name for current request
42
7
  def current_resources_name
43
8
  @current_resources_name ||= params[:resources]
@@ -338,7 +338,6 @@ module Wallaby
338
338
  extend Baseable::ClassMethods
339
339
  extend Decoratable::ClassMethods
340
340
  extend Paginatable::ClassMethods
341
- extend Resourcable::ClassMethods
342
341
  extend Servicable::ClassMethods
343
342
 
344
343
  include View
@@ -351,6 +350,8 @@ module Wallaby
351
350
  include Resourcable
352
351
  include Servicable
353
352
 
353
+ base_class!
354
+
354
355
  # NOTE: to ensure Wallaby's layout
355
356
  # is not inheriting from/impacted by parent controller's layout.
356
357
  public_send(
@@ -364,7 +365,7 @@ module Wallaby
364
365
  respond_to :json
365
366
  respond_to :csv
366
367
  helper ResourcesHelper
367
- before_action :authenticate_user!
368
+ before_action :authenticate_wallaby_user!
368
369
 
369
370
  def home
370
371
  # do nothing
@@ -20,7 +20,7 @@ module Wallaby
20
20
  # @return [Class] model servicer
21
21
  # @raise [ArgumentError] when **model_servicer** doesn't inherit from **application_servicer**
22
22
  # @see Wallaby::ModelServicer
23
- # @since 5.2.0
23
+ # @since wallaby-5.2.0
24
24
  attr_reader :model_servicer
25
25
 
26
26
  # @!attribute [w] application_servicer
@@ -38,7 +38,7 @@ module Wallaby
38
38
  # @return [Class] application decorator
39
39
  # @raise [ArgumentError] when **model_servicer** doesn't inherit from **application_servicer**
40
40
  # @see Wallaby::ModelServicer
41
- # @since 5.2.0
41
+ # @since wallaby-5.2.0
42
42
  def application_servicer
43
43
  @application_servicer ||= ModuleUtils.try_to superclass, :application_servicer
44
44
  end
@@ -49,12 +49,12 @@ module Wallaby
49
49
  # - controller configuration {Wallaby::Servicable::ClassMethods#model_servicer .model_servicer}
50
50
  # - a generic servicer based on {Wallaby::Servicable::ClassMethods#application_servicer .application_servicer}
51
51
  # @return [Wallaby::ModelServicer] model servicer
52
- # @since 5.2.0
52
+ # @since wallaby-5.2.0
53
53
  def current_servicer
54
54
  @current_servicer ||=
55
55
  (controller_to_get(:model_servicer) \
56
56
  || Map.servicer_map(current_model_class, controller_to_get(:application_servicer))).try do |klass|
57
- Logger.debug %(Current servicer: #{klass})
57
+ Logger.debug %(Current servicer: #{klass}), sourcing: false
58
58
  klass.new current_model_class, current_authorizer, current_model_decorator
59
59
  end
60
60
  end
@@ -1,10 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wallaby
4
- # Resource Decorator base class, designed for decorator pattern.
5
- # @see Wallaby::ModelDecorator
4
+ # Decorator base class. It's designed to be used as the decorator (AKA presenter/view object)
5
+ # for the associated model instance (which means it should be used in the views only).
6
+ #
7
+ # And it holds the following metadata information for associated model class:
8
+ #
9
+ # - {#fields}
10
+ # - {#field_names}
11
+ # - {#index_fields}
12
+ # - {#index_field_names}
13
+ # - {#show_fields}
14
+ # - {#show_field_names}
15
+ # - {#form_fields}
16
+ # - {#form_field_names}
17
+ #
18
+ # For better practice, please create an application decorator class (see example)
19
+ # to better control the functions shared between different resource decorators.
20
+ # @example Create an application class for Admin Interface usage
21
+ # class Admin::ApplicationDecorator < Wallaby::ResourceDecorator
22
+ # base_class!
23
+ # end
6
24
  class ResourceDecorator
7
25
  extend Baseable::ClassMethods
26
+ base_class!
27
+
28
+ # @!attribute fields
29
+ # (see Wallaby::ModelDecorator#fields)
30
+
31
+ # @!attribute field_names
32
+ # (see Wallaby::ModelDecorator#field_names)
33
+
34
+ # @!attribute index_fields
35
+ # (see Wallaby::ModelDecorator#index_fields)
36
+
37
+ # @!attribute index_field_names
38
+ # (see Wallaby::ModelDecorator#index_field_names)
39
+
40
+ # @!attribute show_fields
41
+ # (see Wallaby::ModelDecorator#show_fields)
42
+
43
+ # @!attribute show_field_names
44
+ # (see Wallaby::ModelDecorator#show_field_names)
45
+
46
+ # @!attribute form_fields
47
+ # (see Wallaby::ModelDecorator#form_fields)
48
+
49
+ # @!attribute form_field_names
50
+ # (see Wallaby::ModelDecorator#form_field_names)
8
51
 
9
52
  DELEGATE_METHODS =
10
53
  ModelDecorator.public_instance_methods(false) + Fieldable.public_instance_methods(false) - %i(model_class)
@@ -12,85 +55,15 @@ module Wallaby
12
55
  class << self
13
56
  delegate(*DELEGATE_METHODS, to: :model_decorator, allow_nil: true)
14
57
 
15
- # @!attribute [w] model_class
16
- attr_writer :model_class
17
-
18
- # @!attribute [r] model_class
19
- # Return associated model class, e.g. return **Product** for **ProductDecorator**.
20
- #
21
- # If Wallaby can't recognise the model class for Decorator, it's required to be configured as below example:
22
- # @example To configure model class
23
- # class Admin::ProductDecorator < Admin::ApplicationDecorator
24
- # self.model_class = Product
25
- # end
26
- # @example To configure model class for version below 5.2.0
27
- # class Admin::ProductDecorator < Admin::ApplicationDecorator
28
- # def self.model_class
29
- # Product
30
- # end
31
- # end
32
- # @return [Class] assoicated model class
33
- # @return [nil] if current class is marked as base class
34
- # @return [nil] if current class is the same as the value of {Wallaby::Configuration::Mapping#resource_decorator}
35
- # @return [nil] if current class is {Wallaby::ResourceDecorator}
36
- # @return [nil] if assoicated model class is not found
37
- def model_class
38
- return unless self < ResourceDecorator
39
- return if base_class? || self == Wallaby.configuration.mapping.resource_decorator
40
-
41
- @model_class ||= Map.model_class_map(name.gsub(/(^#{namespace}::)|(Decorator$)/, EMPTY_STRING))
42
- end
43
-
44
- # @!attribute [w] application_decorator
45
- def application_decorator=(application_decorator)
46
- ModuleUtils.inheritance_check self, application_decorator
47
- @application_decorator = application_decorator
48
- end
49
-
50
- # @note This attribute have to be the same as the one defined in the controller in order to make things working.
51
- # see {Wallaby::Decoratable::ClassMethods#application_decorator}
52
- # @!attribute [r] application_decorator
53
- # Assoicated base class.
54
- #
55
- # Wallaby will try to get the application decorator class from current class's ancestors chain.
56
- # For instance, if current class is **ProductDecorator**, and it inherits from **CoreDecorator**,
57
- # then Wallaby will return application decorator class **CoreDecorator**.
58
- #
59
- # However, there is a chance that Wallaby doesn't get it right.
60
- # For instance, if **CoreDecorator** in the above example inherits from **Admin::ApplicationDecorator**, and
61
- # the controller that needs **ProductDecorator** has set its **application_decorator** to
62
- # **Admin::ApplicationDecorator**, then it's needed to configure **application_decorator** as the example
63
- # describes
64
- # @example To set application decorator class
65
- # class ProductController < Admin::ApplicationController
66
- # self.application_decorator = Admin::ApplicationDecorator
67
- # end
68
- #
69
- # class CoreDecorator < Admin::ApplicationDecorator
70
- # base_class!
71
- # end
72
- #
73
- # class ProductDecorator < CoreDecorator
74
- # self.application_decorator = Admin::ApplicationDecorator
75
- # end
76
- # @return [Class] assoicated base class.
77
- # @return [nil] if assoicated base class is not found from its ancestors chain
78
- # @raise [ArgumentError] when current class doesn't inherit from given value
79
- # @since 5.2.0
80
- def application_decorator
81
- @application_decorator ||= ancestors.find { |parent| parent < ResourceDecorator && !parent.model_class }
82
- end
83
-
84
- # Return associated model decorator.
85
- #
86
- # Fetch model decorator instance from cached map using keys {.model_class} and {.application_decorator}
87
- # so that model decorator can be used in its sub classes declaration/scope.
58
+ # Return associated model decorator. It is the instance that pull out all the metadata
59
+ # information for the associated model.
88
60
  # @param model_class [Class]
89
61
  # @return [Wallaby::ModelDecorator]
62
+ # @return [nil] if itself is a base class or the given model_class is blank
90
63
  def model_decorator(model_class = self.model_class)
91
- return unless self < ResourceDecorator || model_class
64
+ return if model_class.blank?
92
65
 
93
- Map.model_decorator_map model_class, application_decorator
66
+ Map.model_decorator_map model_class, base_class
94
67
  end
95
68
 
96
69
  # @!attribute [w] h
@@ -164,13 +137,13 @@ module Wallaby
164
137
 
165
138
  # @return [ActiveModel::Name]
166
139
  def model_name
167
- ModuleUtils.try_to(resource, :model_name) || ActiveModel::Name.new(model_class)
140
+ resource.try(:model_name) || ActiveModel::Name.new(model_class)
168
141
  end
169
142
 
170
143
  # @return [nil] if no primary key
171
144
  # @return [Array<String>] primary key
172
145
  def to_key
173
- key = ModuleUtils.try_to(resource, primary_key)
146
+ key = resource.try primary_key
174
147
  key ? [key] : nil
175
148
  end
176
149
 
@@ -181,7 +154,7 @@ module Wallaby
181
154
  resource.try method_id, *args, &block
182
155
  end
183
156
 
184
- # Delegate missing method check to context
157
+ # Delegate missing method check to {#resource}
185
158
  def respond_to_missing?(method_id, _include_private)
186
159
  resource.respond_to?(method_id) || super
187
160
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ class ClassNotFound < GeneralError
5
+ end
6
+ end
@@ -5,6 +5,8 @@ module Wallaby
5
5
  class ModelNotFound < NotFound
6
6
  # @return [String] not found error message
7
7
  def message
8
+ return super if super.include? "\n"
9
+
8
10
  Locale.t 'errors.not_found.model', model: super
9
11
  end
10
12
  end
@@ -3,6 +3,9 @@
3
3
  module Wallaby
4
4
  # Resources helper
5
5
  module ResourcesHelper
6
+ include ApplicationHelper
7
+ include SecureHelper
8
+
6
9
  include BaseHelper
7
10
  include FormHelper
8
11
  include IndexHelper
@@ -9,7 +9,7 @@ module Wallaby
9
9
  # - otherwise, an user icon will be returned
10
10
  # @param user [Object]
11
11
  # @return [String] IMG or I element
12
- def user_portrait(user = current_user)
12
+ def user_portrait(user = wallaby_user)
13
13
  email_method = security.email_method || :email
14
14
  email = try_to user, email_method
15
15
  if email.present?
@@ -27,7 +27,7 @@ module Wallaby
27
27
  # @param user [Object]
28
28
  # @param app [Object]
29
29
  # @return [String] URL to log out
30
- def logout_path(user = current_user, app = main_app)
30
+ def logout_path(user = wallaby_user, app = main_app)
31
31
  path = security.logout_path
32
32
  path ||=
33
33
  if defined? ::Devise
@@ -41,7 +41,7 @@ module Wallaby
41
41
  # @see Wallaby::Configuration::Security#logout_method
42
42
  # @param user [Object]
43
43
  # @return [String, Symbol] http method to log out
44
- def logout_method(user = current_user)
44
+ def logout_method(user = wallaby_user)
45
45
  http_method = security.logout_method
46
46
  http_method ||
47
47
  if defined? ::Devise
@@ -24,14 +24,14 @@ module Wallaby
24
24
 
25
25
  # @see Wallaby::ModelPaginationProvider
26
26
  # @return [Class] pagination provider for the mode
27
- # @since 5.2.0
27
+ # @since wallaby-5.2.0
28
28
  def model_pagination_provider
29
29
  check_and_constantize __callee__
30
30
  end
31
31
 
32
32
  # @see Wallaby::ModelPaginationProvider
33
33
  # @return [Class] pagination provider for the mode
34
- # @since 5.2.0
34
+ # @since wallaby-5.2.0
35
35
  def default_authorization_provider
36
36
  check_and_constantize __callee__
37
37
  end
@@ -39,7 +39,7 @@ module Wallaby
39
39
  # Return a list of authorization providers for authorizer to detect which one to use.
40
40
  # @see Wallaby::ModelAuthorizationProvider
41
41
  # @return [ActiveSupport::HashWithIndifferentAccess<String, Class>] authorization provider hash
42
- # @since 5.2.0
42
+ # @since wallaby-5.2.0
43
43
  def model_authorization_providers(classes = ModelAuthorizationProvider.descendants)
44
44
  # NOTE: make sure default provider always comes last
45
45
  @model_authorization_providers ||=
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  # Model Authorizer interface.
5
- # @since 5.2.0
5
+ # @since wallaby-5.2.0
6
6
  class ModelAuthorizationProvider
7
7
  class << self
8
8
  # @!attribute [w] provider_name
@@ -13,34 +13,36 @@ module Wallaby
13
13
  # @see Wallaby::ModelAuthorizer.provider_name
14
14
  # @return [String/Symbol] provider name
15
15
  def provider_name
16
- @provider_name || name.demodulize.gsub(/(Authorization)?Provider/, EMPTY_STRING).underscore
16
+ @provider_name ||= name.demodulize.gsub(/(Authorization)?Provider/, EMPTY_STRING).underscore
17
17
  end
18
18
 
19
19
  # @note Template method to check and see if current provider is in used.
20
- # @param _context [ActionController::Base]
20
+ # @param _context [ActionController::Base, ActionView::Base]
21
21
  # @raise [Wallaby::NotImplemented]
22
22
  def available?(_context)
23
23
  raise NotImplemented
24
24
  end
25
-
26
- # @note Template method to pull out the args required for contruction from context.
27
- # @param _context [ActionController::Base]
28
- # @raise [Wallaby::NotImplemented]
29
- def args_from(_context)
30
- raise NotImplemented
31
- end
32
25
  end
33
26
 
34
27
  # @!attribute [r] context
35
- # @return [ActionController::Base]
28
+ # @return [ActionController::Base, ActionView::Base]
36
29
  attr_reader :context
37
30
 
38
31
  # @!attribute [r] user
39
32
  # @return [Object]
40
33
  attr_reader :user
41
34
 
42
- # Empty initialize that accepts all sorts of args
43
- def initialize(*); end
35
+ # @!attribute [r] options
36
+ # @return [Hash]
37
+ attr_reader :options
38
+
39
+ # @param context [ActionController::Base, ActionView::Base]
40
+ # @param options [Hash]
41
+ def initialize(context, **options)
42
+ @context = context
43
+ @options = options
44
+ @user = context.try :wallaby_user
45
+ end
44
46
 
45
47
  # @note It can be overridden in subclasses for customization purpose.
46
48
  # This is the template method to check user's permission for given action on given subject.