wallaby-core 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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.