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
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ # This is a constant-safe array that stores Class value as String.
5
+ class ClassArray
6
+ include Classifier
7
+
8
+ # @param [Array] array
9
+ def initialize(array = [])
10
+ @internal = array || []
11
+ return if @internal.blank?
12
+
13
+ @internal.map!(&method(:to_class_name)).compact!
14
+ end
15
+
16
+ # @!attribute [r] internal
17
+ # @return [Array] The array to store Class values as String.
18
+ attr_reader :internal
19
+
20
+ # @!attribute [r] origin
21
+ # @return [Array] The original array.
22
+ def origin
23
+ # NOTE: DO NOT cache it by using instance variable!
24
+ @internal.map(&method(:to_class)).compact
25
+ end
26
+
27
+ # Save the value to the {#internal} array at the given index, and convert the Class value to String
28
+ def []=(index, value)
29
+ @internal[index] = to_class_name value
30
+ end
31
+
32
+ # Return the value for the given index
33
+ def [](index)
34
+ to_class @internal[index]
35
+ end
36
+
37
+ # @param other [Array]
38
+ # @return [Wallaby::ClassArray] new Class array
39
+ def concat(other)
40
+ self.class.new origin.concat(other.try(:origin) || other)
41
+ end
42
+
43
+ # @param other [Array]
44
+ # @return [Wallaby::ClassArray] new Class array
45
+ def -(other)
46
+ self.class.new origin - (other.try(:origin) || other)
47
+ end
48
+
49
+ # @return [Wallaby::ClassArray] self
50
+ def each(&block)
51
+ origin.each(&block)
52
+ self
53
+ end
54
+
55
+ # @!method ==(other)
56
+ # Compare #{origin} with other.
57
+ delegate :==, to: :origin
58
+
59
+ # @!method blank?
60
+ delegate :blank?, to: :internal
61
+
62
+ # @!method each_with_object(object)
63
+ delegate :each_with_object, to: :origin
64
+
65
+ # @!method to_sentence
66
+ delegate :to_sentence, to: :origin
67
+
68
+ # Ensure to freeze the {#internal}
69
+ # @return [Wallaby::ClassArray] self
70
+ def freeze
71
+ @internal.freeze
72
+ super
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ # This is a constant-safe hash that stores Class key/value as String
5
+ # and returns value as Class if it was a Class.
6
+ #
7
+ # It can be used for global methods (e.g. {Wallaby::Map.mode_map}) which cache the computed result,
8
+ # so that when Rails reloads, it won't complain that old Class constants still exist in
9
+ # ObjectSpace (see https://github.com/wallaby-rails/wallaby/issues/181).
10
+ #
11
+ # ```
12
+ # A copy of SupportAdmin::ApplicationAuthorizer has been removed from the module tree but is still active!
13
+ # ```
14
+ #
15
+ # As there won't be any Class constants being stored, they will converted to String in {#internal} Hash.
16
+ class ClassHash
17
+ # @!attribute [r] internal
18
+ # @return [Hash] The hash to store Class keys/values as String.
19
+ attr_reader :internal
20
+
21
+ # @param [Hash] hash
22
+ def initialize(hash = {})
23
+ @internal =
24
+ (hash || {})
25
+ .transform_keys(&method(:to_class_name))
26
+ .transform_values(&method(:to_class_name))
27
+ end
28
+
29
+ # @!attribute [r] origin
30
+ # @return [Hash] The original hash.
31
+ def origin
32
+ # NOTE: DO NOT cache it by using instance variable!
33
+ @internal
34
+ .transform_keys(&method(:to_class))
35
+ .transform_values(&method(:to_class))
36
+ .reject { |k, v| k.nil? || v.nil? }
37
+ end
38
+
39
+ # @!method keys
40
+ # Return the keys of {#origin}.
41
+ delegate :keys, to: :origin
42
+
43
+ # @!method values
44
+ # Return the values of {#origin}.
45
+ delegate :values, to: :origin
46
+
47
+ # @!method ==(other)
48
+ # Compare #{origin} with other.
49
+ delegate :==, to: :origin
50
+
51
+ # Save the key/value to the {#internal} hash, and convert the Class key/value to String
52
+ def []=(key, value)
53
+ @internal[to_class_name(key)] = to_class_name(value)
54
+ end
55
+
56
+ # Return the value for the given key, and convert the value back to Class if it was a Class
57
+ def [](key)
58
+ to_class @internal[to_class_name(key)]
59
+ end
60
+
61
+ # @param other [Hash]
62
+ # @return [Wallaby::ClassHash] new Class hash
63
+ def merge(other)
64
+ self.class.new origin.merge(other.try(:origin) || other)
65
+ end
66
+
67
+ # @return [Wallaby::ClassHash] new Class hash
68
+ def select(&block)
69
+ self.class.new origin.select(&block)
70
+ end
71
+
72
+ # Ensure to freeze the {#internal}
73
+ # @return [Wallaby::ClassHash] self
74
+ def freeze
75
+ @internal.freeze
76
+ super
77
+ end
78
+
79
+ protected
80
+
81
+ # Convert to Class name
82
+ def to_class_name(klass)
83
+ klass.is_a?(Class) ? [klass.name, true] : [klass, false]
84
+ end
85
+
86
+ # Convert to Class
87
+ def to_class(pair)
88
+ val, is_class = pair
89
+ is_class ? val.constantize : val
90
+ rescue NameError
91
+ Logger.error "`#{val}` is not a valid Class name."
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wallaby
4
+ # Concern to handle the conversion between Class and String
5
+ module Classifier
6
+ # Convert Class to String. If not Class, unchanged.
7
+ # @param klass [Object]
8
+ # @return [String] if klass is a Class
9
+ # @return [Object] if klass is not a Class
10
+ def to_class_name(klass)
11
+ klass.try(:name) || klass || nil
12
+ end
13
+
14
+ # Convert String to Class. If not String, unchanged.
15
+ # @param name [Object]
16
+ # @return [Class] if name is a Class
17
+ # @return [Object] if name is not a String
18
+ # @return [nil] if class cannot be found
19
+ def to_class(name)
20
+ return name unless name.is_a? String
21
+
22
+ # NOTE: DO NOT try to use const_defined? and const_get EVER.
23
+ # This is Rails, use constantize
24
+ name.constantize
25
+ rescue NameError
26
+ Logger.error "`#{name}` is not a valid Class name."
27
+ end
28
+ end
29
+ end
@@ -4,8 +4,37 @@
4
4
  module Wallaby
5
5
  # Global configuration
6
6
  class Configuration
7
+ include Classifier
8
+
9
+ # @!attribute [w] model_paths
10
+ def model_paths=(*model_paths)
11
+ @model_paths =
12
+ model_paths.flatten.compact.presence.try do |paths|
13
+ next paths if paths.all? { |p| p.is_a?(String) }
14
+
15
+ raise(
16
+ ArgumentError,
17
+ 'Please provide a list of string paths, e.g. `["app/models", "app/core"]`'
18
+ )
19
+ end
20
+ end
21
+
22
+ # @!attribute [r] model_paths
23
+ # To configure the model folders that {Wallaby::Preloader} needs to load before everything else.
24
+ # @example To set the model paths
25
+ # Wallaby.config do |config|
26
+ # config.model_paths = ["app/models", "app/core"]
27
+ # end
28
+ # @return [Array<String>] model paths
29
+ # @since 0.2.2
30
+ def model_paths
31
+ @model_paths ||= %w(app/models)
32
+ end
33
+
7
34
  # @!attribute [w] base_controller
8
- attr_writer :base_controller
35
+ def base_controller=(base_controller)
36
+ @base_controller = to_class_name base_controller
37
+ end
9
38
 
10
39
  # @!attribute [r] base_controller
11
40
  # To globally configure the base controller class that {Wallaby::ApplicationController} should inherit from.
@@ -18,7 +47,7 @@ module Wallaby
18
47
  # end
19
48
  # @return [Class] base controller class
20
49
  def base_controller
21
- @base_controller ||= ::ApplicationController
50
+ to_class @base_controller ||= '::ApplicationController'
22
51
  end
23
52
 
24
53
  # @return [Wallaby::Configuration::Models] models configuration for custom mode
@@ -3,10 +3,14 @@
3
3
  module Wallaby
4
4
  class Configuration
5
5
  # Configuration used in {Wallaby::Map}
6
- # @since 5.1.6
6
+ # @since wallaby-5.1.6
7
7
  class Mapping
8
+ include Classifier
9
+
8
10
  # @!attribute [w] resources_controller
9
- attr_writer :resources_controller
11
+ def resources_controller=(resources_controller)
12
+ @resources_controller = to_class_name resources_controller
13
+ end
10
14
 
11
15
  # @!attribute [r] resources_controller
12
16
  # To globally configure the resources controller.
@@ -21,17 +25,19 @@ module Wallaby
21
25
  # config.mapping.resources_controller = ::GlobalResourcesController
22
26
  # end
23
27
  # @return [Class] resources controller class
24
- # @since 5.1.6
28
+ # @since wallaby-5.1.6
25
29
  def resources_controller
26
30
  @resources_controller ||=
27
31
  defined?(::Admin::ApplicationController) \
28
32
  && ::Admin::ApplicationController < ::Wallaby::ResourcesController \
29
- && ::Admin::ApplicationController
30
- @resources_controller ||= ResourcesController
33
+ && 'Admin::ApplicationController'
34
+ to_class @resources_controller ||= 'Wallaby::ResourcesController'
31
35
  end
32
36
 
33
37
  # @!attribute [w] resource_decorator
34
- attr_writer :resource_decorator
38
+ def resource_decorator=(resource_decorator)
39
+ @resource_decorator = to_class_name resource_decorator
40
+ end
35
41
 
36
42
  # @!attribute [r] resource_decorator
37
43
  # To globally configure the resource decorator.
@@ -46,17 +52,19 @@ module Wallaby
46
52
  # config.mapping.resource_decorator = ::GlobalResourceDecorator
47
53
  # end
48
54
  # @return [Class] resource decorator class
49
- # @since 5.1.6
55
+ # @since wallaby-5.1.6
50
56
  def resource_decorator
51
57
  @resource_decorator ||=
52
58
  defined?(::Admin::ApplicationDecorator) \
53
59
  && ::Admin::ApplicationDecorator < ::Wallaby::ResourceDecorator \
54
- && ::Admin::ApplicationDecorator
55
- @resource_decorator ||= ResourceDecorator
60
+ && 'Admin::ApplicationDecorator'
61
+ to_class @resource_decorator ||= 'Wallaby::ResourceDecorator'
56
62
  end
57
63
 
58
64
  # @!attribute [w] model_servicer
59
- attr_writer :model_servicer
65
+ def model_servicer=(model_servicer)
66
+ @model_servicer = to_class_name model_servicer
67
+ end
60
68
 
61
69
  # @!attribute [r] model_servicer
62
70
  # To globally configure the model servicer.
@@ -71,17 +79,19 @@ module Wallaby
71
79
  # config.mapping.model_servicer = ::GlobalModelServicer
72
80
  # end
73
81
  # @return [Class] model servicer class
74
- # @since 5.1.6
82
+ # @since wallaby-5.1.6
75
83
  def model_servicer
76
84
  @model_servicer ||=
77
85
  defined?(::Admin::ApplicationServicer) \
78
86
  && ::Admin::ApplicationServicer < ::Wallaby::ModelServicer \
79
- && ::Admin::ApplicationServicer
80
- @model_servicer ||= ModelServicer
87
+ && 'Admin::ApplicationServicer'
88
+ to_class @model_servicer ||= 'Wallaby::ModelServicer'
81
89
  end
82
90
 
83
91
  # @!attribute [w] model_authorizer
84
- attr_writer :model_authorizer
92
+ def model_authorizer=(model_authorizer)
93
+ @model_authorizer = to_class_name model_authorizer
94
+ end
85
95
 
86
96
  # @!attribute [r] model_authorizer
87
97
  # To globally configure the model authorizer.
@@ -96,17 +106,19 @@ module Wallaby
96
106
  # config.mapping.model_authorizer = ::GlobalModelAuthorizer
97
107
  # end
98
108
  # @return [Class] model authorizer class
99
- # @since 5.2.0
109
+ # @since wallaby-5.2.0
100
110
  def model_authorizer
101
111
  @model_authorizer ||=
102
112
  defined?(::Admin::ApplicationAuthorizer) \
103
113
  && ::Admin::ApplicationAuthorizer < ::Wallaby::ModelAuthorizer \
104
- && ::Admin::ApplicationAuthorizer
105
- @model_authorizer ||= ModelAuthorizer
114
+ && 'Admin::ApplicationAuthorizer'
115
+ to_class @model_authorizer ||= 'Wallaby::ModelAuthorizer'
106
116
  end
107
117
 
108
118
  # @!attribute [w] model_paginator
109
- attr_writer :model_paginator
119
+ def model_paginator=(model_paginator)
120
+ @model_paginator = to_class_name model_paginator
121
+ end
110
122
 
111
123
  # @!attribute [r] model_paginator
112
124
  # To globally configure the resource paginator.
@@ -121,13 +133,13 @@ module Wallaby
121
133
  # config.mapping.model_paginator = ::GlobalModelPaginator
122
134
  # end
123
135
  # @return [Class] resource paginator class
124
- # @since 5.2.0
136
+ # @since wallaby-5.2.0
125
137
  def model_paginator
126
138
  @model_paginator ||=
127
139
  defined?(::Admin::ApplicationPaginator) \
128
140
  && ::Admin::ApplicationPaginator < ::Wallaby::ModelPaginator \
129
- && ::Admin::ApplicationPaginator
130
- @model_paginator ||= ModelPaginator
141
+ && 'Admin::ApplicationPaginator'
142
+ to_class @model_paginator ||= 'Wallaby::ModelPaginator'
131
143
  end
132
144
  end
133
145
  end
@@ -14,7 +14,7 @@ module Wallaby
14
14
  # config.metadata.max = 50
15
15
  # end
16
16
  # @return [Integer] max number of characters to truncate, default to 20
17
- # @since 5.1.6
17
+ # @since wallaby-5.1.6
18
18
  def max
19
19
  @max ||= DEFAULT_MAX
20
20
  end
@@ -2,11 +2,7 @@
2
2
 
3
3
  module Wallaby
4
4
  class Configuration
5
- # @note In `development` environment, Rails recreates module/class constants on reload event.
6
- # If constants are cached/stored, they will become stale and Rails will raise conflicts.
7
- #
8
- # Hence, class name strings should be stored instead.
9
- # When classes are requested, strings will be constantized into classes.
5
+ # @deprecated will move this configuration to {Wallaby::ResourcesController} from 6.2
10
6
  # Models configuration to specify the model classes that Wallaby should handle.
11
7
  class Models
12
8
  # @note If models are whitelisted, models exclusion will NOT be applied.
@@ -17,12 +13,12 @@ module Wallaby
17
13
  # end
18
14
  # @param models [Array<Class, String>]
19
15
  def set(*models)
20
- @models = Array(models).flatten.map(&:to_s)
16
+ @models = ClassArray.new(models.flatten)
21
17
  end
22
18
 
23
19
  # @return [Array<Class>] the models configured
24
20
  def presence
25
- (@models ||= []).map(&:constantize)
21
+ @models ||= ClassArray.new # rubocop:disable Naming/MemoizedInstanceVariableName
26
22
  end
27
23
 
28
24
  # @note If models are whitelisted using {#set}, models exclusion will NOT be applied.
@@ -33,13 +29,13 @@ module Wallaby
33
29
  # end
34
30
  # @param models [Array<Class, String>]
35
31
  def exclude(*models)
36
- @excludes = Array(models).flatten.map(&:to_s)
32
+ @excludes = ClassArray.new(models.flatten)
37
33
  end
38
34
 
39
35
  # @return [Array<Class>] the list of models to exclude.
40
36
  # By default, `ActiveRecord::SchemaMigration` is excluded.
41
37
  def excludes
42
- (@excludes ||= ['ActiveRecord::SchemaMigration']).map(&:constantize)
38
+ @excludes ||= ClassArray.new ['ActiveRecord::SchemaMigration']
43
39
  end
44
40
  end
45
41
  end
@@ -3,6 +3,7 @@
3
3
  module Wallaby
4
4
  class Configuration
5
5
  # Security configuration
6
+ # TODO: remove this from 6.2
6
7
  class Security
7
8
  # Default block to return nil for current user
8
9
  DEFAULT_CURRENT_USER = -> { nil }
@@ -20,7 +21,7 @@ module Wallaby
20
21
  # Wallaby.config do |config|
21
22
  # config.security.logout_path = 'logout_path'
22
23
  # end
23
- # @since 5.1.4
24
+ # @since wallaby-5.1.4
24
25
  attr_accessor :logout_path
25
26
 
26
27
  # @!attribute logout_method
@@ -34,7 +35,7 @@ module Wallaby
34
35
  # Wallaby.config do |config|
35
36
  # config.security.logout_method = 'post'
36
37
  # end
37
- # @since 5.1.4
38
+ # @since wallaby-5.1.4
38
39
  attr_accessor :logout_method
39
40
 
40
41
  # @!attribute email_method
@@ -45,7 +46,7 @@ module Wallaby
45
46
  # Wallaby.config do |config|
46
47
  # config.security.email_method = 'email_address'
47
48
  # end
48
- # @since 5.1.4
49
+ # @since wallaby-5.1.4
49
50
  attr_accessor :email_method
50
51
 
51
52
  # To globally configure how to get user object.
@@ -57,6 +58,7 @@ module Wallaby
57
58
  # end
58
59
  # @yield A block to get user object. All application controller methods can be used in the block.
59
60
  def current_user(&block)
61
+ Logger.deprecated 'Wallaby will remove security.current_user? from 6.2.'
60
62
  if block_given?
61
63
  @current_user = block
62
64
  else
@@ -81,6 +83,7 @@ module Wallaby
81
83
  # end
82
84
  # @yield A block to authenticate user. All application controller methods can be used in the block.
83
85
  def authenticate(&block)
86
+ Logger.deprecated 'Wallaby will remove security.authenticate from 6.2.'
84
87
  if block_given?
85
88
  @authenticate = block
86
89
  else