wallaby-core 0.1.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +60 -13
- data/app/controllers/wallaby/resources_controller.rb +15 -374
- data/app/security/ability.rb +1 -1
- data/config/locales/wallaby.en.yml +92 -128
- data/config/locales/wallaby_class.en.yml +2 -23
- data/lib/adaptors/wallaby/custom/default_provider.rb +1 -1
- data/lib/adaptors/wallaby/custom/model_decorator.rb +8 -7
- data/lib/adaptors/wallaby/custom/model_finder.rb +3 -2
- data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +1 -1
- data/lib/adaptors/wallaby/custom/model_service_provider.rb +1 -40
- data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +30 -24
- data/lib/authorizers/wallaby/default_authorization_provider.rb +6 -13
- data/lib/authorizers/wallaby/model_authorizer.rb +43 -67
- data/lib/authorizers/wallaby/pundit_authorization_provider.rb +21 -30
- data/lib/concerns/wallaby/application_concern.rb +110 -0
- data/lib/concerns/wallaby/authentication_concern.rb +162 -0
- data/lib/concerns/wallaby/authorizable.rb +8 -14
- data/lib/concerns/wallaby/baseable.rb +91 -10
- data/lib/concerns/wallaby/decoratable.rb +3 -3
- data/lib/concerns/wallaby/engineable.rb +1 -1
- data/lib/concerns/wallaby/fieldable.rb +4 -4
- data/lib/concerns/wallaby/paginatable.rb +3 -3
- data/lib/concerns/wallaby/prefixable.rb +21 -0
- data/lib/concerns/wallaby/resourcable.rb +4 -35
- data/lib/concerns/wallaby/resources_concern.rb +434 -0
- data/lib/concerns/wallaby/servicable.rb +4 -10
- data/lib/decorators/wallaby/resource_decorator.rb +53 -80
- data/lib/errors/wallaby/{cell_handling.rb → class_not_found.rb} +1 -1
- data/lib/errors/wallaby/model_not_found.rb +3 -1
- data/lib/errors/wallaby/resource_not_found.rb +1 -1
- data/lib/helpers/wallaby/application_helper.rb +6 -9
- data/lib/helpers/wallaby/form_helper.rb +2 -9
- data/lib/helpers/wallaby/index_helper.rb +2 -14
- data/lib/helpers/wallaby/links_helper.rb +5 -5
- data/lib/helpers/wallaby/resources_helper.rb +3 -7
- data/lib/helpers/wallaby/secure_helper.rb +3 -3
- data/lib/helpers/wallaby/styling_helper.rb +17 -3
- data/lib/interfaces/wallaby/mode.rb +5 -5
- data/lib/interfaces/wallaby/model_authorization_provider.rb +15 -13
- data/lib/interfaces/wallaby/model_decorator.rb +15 -3
- data/lib/paginators/wallaby/model_paginator.rb +14 -45
- data/lib/parsers/wallaby/parser.rb +49 -14
- data/lib/routes/wallaby/resources_router.rb +1 -1
- data/lib/servicers/wallaby/model_servicer.rb +32 -62
- data/lib/services/wallaby/map/mode_mapper.rb +14 -14
- data/lib/services/wallaby/map/model_class_collector.rb +2 -2
- data/lib/services/wallaby/map/model_class_mapper.rb +7 -26
- data/lib/services/wallaby/prefixes_builder.rb +15 -49
- data/lib/services/wallaby/type_renderer.rb +3 -13
- data/lib/utils/wallaby/locale.rb +53 -0
- data/lib/utils/wallaby/model_utils.rb +4 -3
- data/lib/utils/wallaby/module_utils.rb +1 -1
- data/lib/utils/wallaby/utils.rb +10 -15
- data/lib/wallaby/class_array.rb +75 -0
- data/lib/wallaby/class_hash.rb +94 -0
- data/lib/wallaby/classifier.rb +29 -0
- data/lib/wallaby/configuration/mapping.rb +33 -27
- data/lib/wallaby/configuration/metadata.rb +1 -1
- data/lib/wallaby/configuration/models.rb +5 -9
- data/lib/wallaby/configuration/security.rb +6 -3
- data/lib/wallaby/configuration/sorting.rb +1 -1
- data/lib/wallaby/configuration.rb +31 -2
- data/lib/wallaby/constants.rb +10 -8
- data/lib/wallaby/core/version.rb +1 -1
- data/lib/wallaby/core.rb +21 -16
- data/lib/wallaby/engine.rb +9 -20
- data/lib/wallaby/logger.rb +35 -0
- data/lib/wallaby/map.rb +20 -17
- data/lib/wallaby/preloader.rb +77 -0
- metadata +48 -22
- data/app/controllers/wallaby/application_controller.rb +0 -84
- data/app/controllers/wallaby/secure_controller.rb +0 -81
- data/lib/concerns/wallaby/rails_overridden_methods.rb +0 -42
- data/lib/concerns/wallaby/themeable.rb +0 -40
- data/lib/paginators/wallaby/resource_paginator.rb +0 -12
- data/lib/renderers/wallaby/cell.rb +0 -137
- data/lib/renderers/wallaby/cell_resolver.rb +0 -89
- data/lib/renderers/wallaby/custom_lookup_context.rb +0 -64
- data/lib/renderers/wallaby/custom_partial_renderer.rb +0 -33
- data/lib/renderers/wallaby/custom_renderer.rb +0 -16
- data/lib/utils/wallaby/cell_utils.rb +0 -34
- data/lib/utils/wallaby/preload_utils.rb +0 -44
@@ -1,45 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Wallaby
|
4
|
-
#
|
4
|
+
# This is the base servicer class to provider data source related operations
|
5
|
+
# for given/associated model. In general, it works together with {#authorizer}
|
6
|
+
# to ensure that all operations are legitmate.
|
7
|
+
#
|
8
|
+
# For best practice, please create an application servicer class (see example)
|
9
|
+
# to better control the functions shared between different model servicers.
|
10
|
+
# @example Create an application class for Admin Interface usage
|
11
|
+
# class Admin::ApplicationServicer < Wallaby::ModelServicer
|
12
|
+
# base_class!
|
13
|
+
# end
|
5
14
|
class ModelServicer
|
6
15
|
extend Baseable::ClassMethods
|
7
|
-
|
8
|
-
class << self
|
9
|
-
# @!attribute [w] model_class
|
10
|
-
attr_writer :model_class
|
11
|
-
|
12
|
-
# @!attribute [r] model_class
|
13
|
-
# Return associated model class, e.g. return **Product** for **ProductServicer**.
|
14
|
-
#
|
15
|
-
# If Wallaby can't recognise the model class for Servicer, it's required to be configured as below example:
|
16
|
-
# @example To configure model class
|
17
|
-
# class Admin::ProductServicer < Admin::ApplicationServicer
|
18
|
-
# self.model_class = Product
|
19
|
-
# end
|
20
|
-
# @example To configure model class for version below 5.2.0
|
21
|
-
# class Admin::ProductServicer < Admin::ApplicationServicer
|
22
|
-
# def self.model_class
|
23
|
-
# Product
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
# @return [Class] assoicated model class
|
27
|
-
# @return [nil] if current class is marked as base class
|
28
|
-
# @return [nil] if current class is the same as the value of {Wallaby::Configuration::Mapping#model_servicer}
|
29
|
-
# @return [nil] if current class is {Wallaby::ModelServicer}
|
30
|
-
# @return [nil] if assoicated model class is not found
|
31
|
-
def model_class
|
32
|
-
return unless self < ModelServicer
|
33
|
-
return if base_class? || self == Wallaby.configuration.mapping.model_servicer
|
34
|
-
|
35
|
-
@model_class ||= Map.model_class_map(name.gsub(/(^#{namespace}::)|(Servicer$)/, EMPTY_STRING))
|
36
|
-
end
|
37
|
-
|
38
|
-
# @!attribute provider_class
|
39
|
-
# @return [Class] service provider class
|
40
|
-
# @since 5.2.0
|
41
|
-
attr_accessor :provider_class
|
42
|
-
end
|
16
|
+
base_class!
|
43
17
|
|
44
18
|
# @!attribute [r] model_class
|
45
19
|
# @return [Class]
|
@@ -47,46 +21,41 @@ module Wallaby
|
|
47
21
|
|
48
22
|
# @!attribute [r] model_decorator
|
49
23
|
# @return [Wallaby::ModelDecorator]
|
50
|
-
# @since 5.2.0
|
24
|
+
# @since wallaby-5.2.0
|
51
25
|
attr_reader :model_decorator
|
52
26
|
|
53
27
|
# @!attribute [r] authorizer
|
54
28
|
# @return [Wallaby::ModelAuthorizer]
|
55
|
-
# @since 5.2.0
|
29
|
+
# @since wallaby-5.2.0
|
56
30
|
attr_reader :authorizer
|
57
31
|
|
58
32
|
# @!attribute [r] provider
|
59
|
-
# @return [Wallaby::ModelServiceProvider]
|
60
|
-
# @since 5.2.0
|
33
|
+
# @return [Wallaby::ModelServiceProvider] the instance that does the job
|
34
|
+
# @since wallaby-5.2.0
|
61
35
|
attr_reader :provider
|
62
36
|
|
63
37
|
# @!method user
|
64
38
|
# @return [Object]
|
65
|
-
# @since 5.2.0
|
39
|
+
# @since wallaby-5.2.0
|
66
40
|
delegate :user, to: :authorizer
|
67
41
|
|
68
|
-
# During initialization, Wallaby will assign a service provider for this servicer
|
69
|
-
# to carry out the actual execution.
|
70
|
-
#
|
71
|
-
# Therefore, all its actions can be completely replaced by user's own implemnetation.
|
72
42
|
# @param model_class [Class]
|
73
43
|
# @param authorizer [Wallaby::ModelAuthorizer]
|
74
44
|
# @param model_decorator [Wallaby::ModelDecorator]
|
75
|
-
# @raise [ArgumentError] if
|
45
|
+
# @raise [ArgumentError] if model_class is blank
|
76
46
|
def initialize(model_class, authorizer, model_decorator = nil)
|
77
47
|
@model_class = model_class || self.class.model_class
|
78
|
-
raise ArgumentError,
|
48
|
+
raise ArgumentError, 'Please provide a `model_class`.' unless @model_class
|
79
49
|
|
80
50
|
@model_decorator = model_decorator || Map.model_decorator_map(model_class)
|
81
51
|
@authorizer = authorizer
|
82
|
-
|
83
|
-
@provider = provider_class.new(@model_class, @model_decorator)
|
52
|
+
@provider = Map.service_provider_map(@model_class).new(@model_class, @model_decorator)
|
84
53
|
end
|
85
54
|
|
86
55
|
# @note This is a template method that can be overridden by subclasses.
|
87
56
|
# Whitelist parameters for mass assignment.
|
88
57
|
# @param params [ActionController::Parameters, Hash]
|
89
|
-
# @param action [String, Symbol]
|
58
|
+
# @param action [String, Symbol, nil]
|
90
59
|
# @return [ActionController::Parameters] permitted params
|
91
60
|
def permit(params, action = nil)
|
92
61
|
provider.permit params, action, authorizer
|
@@ -95,58 +64,59 @@ module Wallaby
|
|
95
64
|
# @note This is a template method that can be overridden by subclasses.
|
96
65
|
# Return a collection by querying the datasource (e.g. database, REST API).
|
97
66
|
# @param params [ActionController::Parameters, Hash]
|
98
|
-
# @return [Enumerable] list of
|
67
|
+
# @return [Enumerable] list of resources
|
99
68
|
def collection(params)
|
100
69
|
provider.collection params, authorizer
|
101
70
|
end
|
102
71
|
|
72
|
+
# @!method paginate(query, params)
|
103
73
|
# @note This is a template method that can be overridden by subclasses.
|
104
74
|
# Paginate given {#collection}.
|
105
75
|
# @param query [Enumerable]
|
106
76
|
# @param params [ActionController::Parameters]
|
107
|
-
# @return [Enumerable] list of
|
77
|
+
# @return [Enumerable] list of resources
|
108
78
|
delegate :paginate, to: :provider
|
109
79
|
|
110
80
|
# @note This is a template method that can be overridden by subclasses.
|
111
81
|
# Initialize an instance of the model class.
|
112
82
|
# @param params [ActionController::Parameters]
|
113
|
-
# @return [Object] initialized
|
83
|
+
# @return [Object] initialized resource
|
114
84
|
def new(params)
|
115
85
|
provider.new params, authorizer
|
116
86
|
end
|
117
87
|
|
118
88
|
# @note This is a template method that can be overridden by subclasses.
|
119
|
-
# To find a
|
89
|
+
# To find a resource.
|
120
90
|
# @param id [Object]
|
121
91
|
# @param params [ActionController::Parameters]
|
122
|
-
# @return [Object] resource
|
92
|
+
# @return [Object] found resource
|
123
93
|
def find(id, params)
|
124
94
|
provider.find id, params, authorizer
|
125
95
|
end
|
126
96
|
|
127
97
|
# @note This is a template method that can be overridden by subclasses.
|
128
|
-
# To create a
|
98
|
+
# To create a resource.
|
129
99
|
# @param resource [Object]
|
130
100
|
# @param params [ActionController::Parameters]
|
131
|
-
# @return [Object] resource
|
101
|
+
# @return [Object] created resource
|
132
102
|
def create(resource, params)
|
133
103
|
provider.create resource, params, authorizer
|
134
104
|
end
|
135
105
|
|
136
106
|
# @note This is a template method that can be overridden by subclasses.
|
137
|
-
# To update a
|
107
|
+
# To update a resource.
|
138
108
|
# @param resource [Object]
|
139
109
|
# @param params [ActionController::Parameters]
|
140
|
-
# @return [Object] resource
|
110
|
+
# @return [Object] resource
|
141
111
|
def update(resource, params)
|
142
112
|
provider.update resource, params, authorizer
|
143
113
|
end
|
144
114
|
|
145
115
|
# @note This is a template method that can be overridden by subclasses.
|
146
|
-
# To delete a
|
116
|
+
# To delete a resource.
|
147
117
|
# @param resource [Object]
|
148
118
|
# @param params [ActionController::Parameters]
|
149
|
-
# @return [Object] resource
|
119
|
+
# @return [Object] resource
|
150
120
|
def destroy(resource, params)
|
151
121
|
provider.destroy resource, params, authorizer
|
152
122
|
end
|
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
module Wallaby
|
4
4
|
class Map
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Go through each {Wallaby::Mode} (e.g. **ActiveRecord**/**Her**)
|
6
|
+
# and find out all the model classes respectively.
|
7
|
+
# Then a hash (Model => {Wallaby::Mode}) is constructed
|
8
|
+
# to tell {Wallaby} which {Wallaby::Mode} to use for a given model.
|
7
9
|
class ModeMapper
|
8
|
-
|
9
|
-
def initialize(mode_classes)
|
10
|
-
@mode_classes = mode_classes
|
11
|
-
end
|
10
|
+
extend Classifier
|
12
11
|
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
# @param class_names [Wallaby::ClassArray] mode class names
|
13
|
+
# @return [WallabyClassHash]
|
14
|
+
def self.execute(class_names)
|
15
|
+
ClassHash.new.tap do |hash|
|
16
|
+
next if class_names.blank?
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
class_names.each_with_object(hash) do |mode_name, map|
|
19
|
+
mode_name.model_finder.new.all.each do |model_class|
|
20
|
+
map[model_class] = mode_name
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -8,7 +8,7 @@ module Wallaby
|
|
8
8
|
# @param models [Array<Class>]
|
9
9
|
def initialize(configuration, models = nil)
|
10
10
|
@configuration = configuration
|
11
|
-
@models = models || []
|
11
|
+
@models = ClassArray.new(models || [])
|
12
12
|
end
|
13
13
|
|
14
14
|
# @return [Array<Class>] model class
|
@@ -26,7 +26,7 @@ module Wallaby
|
|
26
26
|
invalid_models = configured_models - @models
|
27
27
|
return if invalid_models.blank?
|
28
28
|
|
29
|
-
message =
|
29
|
+
message = Locale.t 'errors.invalid.models', models: invalid_models.to_sentence
|
30
30
|
raise InvalidError, message
|
31
31
|
end
|
32
32
|
|
@@ -2,37 +2,18 @@
|
|
2
2
|
|
3
3
|
module Wallaby
|
4
4
|
class Map
|
5
|
-
#
|
5
|
+
# Go through the class list and generate a {.map .map} that uses the class's model_class as the key.
|
6
6
|
class ModelClassMapper
|
7
|
-
# Iterate all classes and generate a hash using their model classes as the key
|
8
|
-
# @see #map
|
9
7
|
# @param class_array [Array<Class>]
|
10
|
-
# @return [
|
11
|
-
def self.map(class_array
|
12
|
-
new
|
13
|
-
|
14
|
-
|
15
|
-
protected
|
8
|
+
# @return [Wallaby::ClassHash] model class => descendant class
|
9
|
+
def self.map(class_array)
|
10
|
+
(class_array || EMPTY_ARRAY).each_with_object(ClassHash.new) do |klass, hash|
|
11
|
+
next if ModuleUtils.anonymous_class?(klass)
|
12
|
+
next if klass.try(:base_class?) || klass.model_class.blank?
|
16
13
|
|
17
|
-
|
18
|
-
def map(class_array)
|
19
|
-
(class_array || EMPTY_ARRAY).each_with_object({}) do |klass, map|
|
20
|
-
next if anonymous?(klass) || base_class?(klass) || !klass.model_class
|
21
|
-
|
22
|
-
map[klass.model_class] = block_given? ? yield(klass) : klass
|
14
|
+
hash[klass.model_class] = block_given? ? yield(klass) : klass
|
23
15
|
end
|
24
16
|
end
|
25
|
-
|
26
|
-
# @see Wallaby::ModuleUtils.anonymous_class?
|
27
|
-
def anonymous?(klass)
|
28
|
-
ModuleUtils.anonymous_class? klass
|
29
|
-
end
|
30
|
-
|
31
|
-
# @param klass [Class]
|
32
|
-
# @return [Boolean] whether the class is base or not
|
33
|
-
def base_class?(klass)
|
34
|
-
ModuleUtils.try_to klass, :base_class?
|
35
|
-
end
|
36
17
|
end
|
37
18
|
end
|
38
19
|
end
|
@@ -3,64 +3,30 @@
|
|
3
3
|
module Wallaby
|
4
4
|
# To extend prefixes to provide more possibility
|
5
5
|
class PrefixesBuilder
|
6
|
-
|
7
|
-
# @param action_name [String] action name
|
8
|
-
# @param resources_name [String] resources name
|
9
|
-
# @param script_name [String] script name
|
10
|
-
# @param theme_name [String] theme name
|
11
|
-
def self.build(origin_prefixes:, action_name:, resources_name:, script_name:, theme_name:)
|
12
|
-
new(
|
13
|
-
origin_prefixes: origin_prefixes,
|
14
|
-
action_name: action_name,
|
15
|
-
resources_name: resources_name,
|
16
|
-
script_name: script_name,
|
17
|
-
theme_name: theme_name
|
18
|
-
).send :build
|
19
|
-
end
|
6
|
+
include ActiveModel::Model
|
20
7
|
|
21
|
-
|
8
|
+
attr_accessor :prefixes
|
9
|
+
attr_accessor :resources_name
|
10
|
+
attr_accessor :script_name
|
22
11
|
|
23
|
-
|
24
|
-
|
25
|
-
@origin_prefixes = origin_prefixes
|
26
|
-
@action_name = action_name
|
27
|
-
@resources_name = resources_name
|
28
|
-
@script_name = script_name
|
29
|
-
@theme_name = theme_name
|
30
|
-
end
|
12
|
+
def execute
|
13
|
+
return if prefixes.include? resources_path
|
31
14
|
|
32
|
-
|
33
|
-
def build
|
34
|
-
prefixes = minimal_prefixes
|
35
|
-
prefixes.unshift mounted_prefix unless prefixes.include? resources_path
|
36
|
-
prefixes.uniq.compact.each_with_object([]) do |prefix, result|
|
37
|
-
result << "#{prefix}/#{suffix}" << prefix
|
38
|
-
end
|
39
|
-
end
|
15
|
+
full_prefix = [script_path, resources_path].compact.join(SLASH)
|
40
16
|
|
41
|
-
|
42
|
-
def minimal_prefixes
|
43
|
-
index = @origin_prefixes.index ResourcesController.controller_path
|
44
|
-
@origin_prefixes.slice(0..index).tap do |prefixes|
|
45
|
-
insert_index = prefixes.length > 1 ? -2 : 0
|
46
|
-
prefixes.insert insert_index, @theme_name if @theme_name.present?
|
47
|
-
end
|
48
|
-
end
|
17
|
+
return if prefixes.include? full_prefix
|
49
18
|
|
50
|
-
|
51
|
-
def mounted_prefix
|
52
|
-
prefix = (@script_name || '').sub(%r{^/}, '')
|
53
|
-
prefix << SLASH if prefix.present?
|
54
|
-
prefix << resources_path if resources_path
|
19
|
+
prefixes.insert 0, full_prefix
|
55
20
|
end
|
56
21
|
|
57
|
-
|
58
|
-
def suffix
|
59
|
-
@suffix ||= CellUtils.to_action_prefix @action_name
|
60
|
-
end
|
22
|
+
private
|
61
23
|
|
62
24
|
def resources_path
|
63
|
-
@resources_path ||=
|
25
|
+
@resources_path ||= resources_name.try :gsub, COLONS, SLASH
|
26
|
+
end
|
27
|
+
|
28
|
+
def script_path
|
29
|
+
@script_path ||= script_name.try :[], 1..-1
|
64
30
|
end
|
65
31
|
end
|
66
32
|
end
|
@@ -23,28 +23,18 @@ module Wallaby
|
|
23
23
|
# @raise [ArgumentError] if field_name is not provided
|
24
24
|
# @raise [ArgumentError] if object is not decorated
|
25
25
|
def check(locals)
|
26
|
-
raise ArgumentError,
|
27
|
-
raise ArgumentError,
|
26
|
+
raise ArgumentError, Locale.t('errors.required', subject: 'form') if locals.key?(:form) && locals[:form].blank?
|
27
|
+
raise ArgumentError, Locale.t('errors.required', subject: 'field_name') if locals[:field_name].blank?
|
28
28
|
raise ArgumentError, 'Object is not decorated.' unless locals[:object].is_a? ResourceDecorator
|
29
29
|
end
|
30
30
|
|
31
31
|
# @param locals [Hash]
|
32
32
|
# @param action [String]
|
33
33
|
def complete(locals, action)
|
34
|
-
action_name =
|
34
|
+
action_name = FORM_ACTIONS[action] || action
|
35
35
|
locals[:metadata] = locals[:object].public_send :"#{action_name}_metadata_of", locals[:field_name]
|
36
36
|
locals[:value] = locals[:object].public_send locals[:field_name]
|
37
37
|
end
|
38
|
-
|
39
|
-
# @param options [String]
|
40
|
-
# @param view [ActionView]
|
41
|
-
# @return [String] partial path string
|
42
|
-
# @return [String] blank string
|
43
|
-
def find_partial(options, view)
|
44
|
-
formats = [view.request.format.to_sym]
|
45
|
-
lookup = view.lookup_context
|
46
|
-
lookup.find_template options, lookup.prefixes, true, [], formats: formats
|
47
|
-
end
|
48
38
|
end
|
49
39
|
end
|
50
40
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Locale related
|
5
|
+
module Locale
|
6
|
+
class << self
|
7
|
+
# Extend translation just for Wallaby
|
8
|
+
# so that translation can be prefixed with `wallaby.`
|
9
|
+
# @param key [String, Symbol, Array]
|
10
|
+
# @param options [Hash] the rest of the arguments
|
11
|
+
# @return [String] translation
|
12
|
+
def t(key, options = {})
|
13
|
+
translator = options.delete(:translator) || I18n.method(:t)
|
14
|
+
return translator.call(key, options) unless key.is_a?(String) || key.is_a?(Symbol)
|
15
|
+
|
16
|
+
new_key, new_defaults = normalize key, options.delete(:default)
|
17
|
+
|
18
|
+
translator.call(new_key, { default: new_defaults }.merge(options))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @param key [String, Symbol, Array]
|
24
|
+
# @param defaults [String, Symbol, Array]
|
25
|
+
# @return [Array]
|
26
|
+
def normalize(key, defaults)
|
27
|
+
*keys, default = *defaults
|
28
|
+
|
29
|
+
# default will NOT be considered as one of the key
|
30
|
+
# if it is not set or if it is a String (since String means translation for I18n.t)
|
31
|
+
unless default.nil? || default.is_a?(String)
|
32
|
+
keys << default
|
33
|
+
default = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
new_defaults = prefix_defaults_from keys.unshift(key)
|
37
|
+
new_key = new_defaults.shift
|
38
|
+
new_defaults << default if default
|
39
|
+
[new_key, new_defaults]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Duplicate and prefix the keys respectively
|
43
|
+
# @param keys [Array]
|
44
|
+
# @return [Array] new_keys
|
45
|
+
def prefix_defaults_from(keys)
|
46
|
+
keys.each_with_object([]) do |k, result|
|
47
|
+
result << :"wallaby.#{k}" unless k.to_s.start_with? 'wallaby.'
|
48
|
+
result << k.to_sym
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Wallaby
|
4
|
-
#
|
4
|
+
# Model related utils
|
5
5
|
module ModelUtils
|
6
6
|
class << self
|
7
7
|
# Convert model class (e.g. `Namespace::Product`) into resources name (e.g. `namespace::products`)
|
@@ -32,10 +32,11 @@ module Wallaby
|
|
32
32
|
return if resources_name.blank?
|
33
33
|
|
34
34
|
class_name = to_model_name resources_name
|
35
|
+
# NOTE: DO NOT try to use const_defined? and const_get EVER.
|
36
|
+
# This is Rails, use constantize
|
35
37
|
class_name.constantize
|
36
38
|
rescue NameError
|
37
|
-
|
38
|
-
nil
|
39
|
+
Logger.warn Locale.t('errors.not_found.model', model: class_name), sourcing: 2..10
|
39
40
|
end
|
40
41
|
|
41
42
|
# Convert resources name (e.g. `namespace::products`) into model name (e.g. `Namespace::Product`)
|
@@ -32,7 +32,7 @@ module Wallaby
|
|
32
32
|
return unless child && parent
|
33
33
|
return if child < parent
|
34
34
|
|
35
|
-
raise ::ArgumentError,
|
35
|
+
raise ::ArgumentError, Locale.t('errors.invalid.inheritance', klass: child, parent: parent)
|
36
36
|
end
|
37
37
|
|
38
38
|
# If block is given, run the block. Otherwise, return subject
|
data/lib/utils/wallaby/utils.rb
CHANGED
@@ -3,25 +3,20 @@
|
|
3
3
|
module Wallaby
|
4
4
|
# Utils
|
5
5
|
module Utils
|
6
|
-
# Display deprecate message including the line where it's used
|
7
|
-
# @param key [String]
|
8
|
-
# @param caller [String] the line where it's called
|
9
|
-
# @param options [Hash]
|
10
|
-
def self.deprecate(key, caller:, options: {})
|
11
|
-
warn I18n.t(key, options.merge(from: caller[0]))
|
12
|
-
end
|
13
|
-
|
14
|
-
# @deprecated Use {Wallaby::FilterUtils.filter_name_by} instead. It will be removed from 5.3.*
|
15
|
-
def self.find_filter_name(filter_name, filters)
|
16
|
-
deprecate 'deprecation.find_filter_name', caller: caller
|
17
|
-
FilterUtils.filter_name_by filter_name, filters
|
18
|
-
end
|
19
|
-
|
20
6
|
# @see http://stackoverflow.com/a/8710663/1326499
|
21
7
|
# @param object [Object]
|
22
8
|
# @return [Object] a clone object
|
23
9
|
def self.clone(object)
|
24
|
-
::Marshal.load(::Marshal.dump(object))
|
10
|
+
object.try(:deep_dup) || object && ::Marshal.load(::Marshal.dump(object))
|
11
|
+
end
|
12
|
+
|
13
|
+
# @param object [Object, nil]
|
14
|
+
# @return [String] inspection string for the given object
|
15
|
+
def self.inspect(object)
|
16
|
+
return 'nil' unless object
|
17
|
+
return object.name if object.is_a? Class
|
18
|
+
|
19
|
+
"#{object.class}##{object.id}"
|
25
20
|
end
|
26
21
|
end
|
27
22
|
end
|
@@ -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
|