hanami-utils 1.3.5 → 2.0.0.alpha2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/README.md +5 -15
- data/hanami-utils.gemspec +19 -16
- data/lib/hanami-utils.rb +3 -1
- data/lib/hanami/interactor.rb +70 -36
- data/lib/hanami/logger.rb +13 -13
- data/lib/hanami/logger/colorizer.rb +10 -10
- data/lib/hanami/logger/filter.rb +74 -9
- data/lib/hanami/logger/formatter.rb +7 -7
- data/lib/hanami/middleware.rb +11 -0
- data/lib/hanami/utils.rb +12 -26
- data/lib/hanami/utils/basic_object.rb +7 -7
- data/lib/hanami/utils/blank.rb +9 -9
- data/lib/hanami/utils/callbacks.rb +24 -3
- data/lib/hanami/utils/class.rb +3 -56
- data/lib/hanami/utils/class_attribute.rb +23 -12
- data/lib/hanami/utils/class_attribute/attributes.rb +45 -0
- data/lib/hanami/utils/deprecation.rb +3 -1
- data/lib/hanami/utils/escape.rb +275 -271
- data/lib/hanami/utils/file_list.rb +24 -2
- data/lib/hanami/utils/files.rb +16 -22
- data/lib/hanami/utils/hash.rb +24 -363
- data/lib/hanami/utils/io.rb +2 -0
- data/lib/hanami/utils/json.rb +5 -3
- data/lib/hanami/utils/kernel.rb +22 -21
- data/lib/hanami/utils/load_paths.rb +6 -4
- data/lib/hanami/utils/path_prefix.rb +38 -6
- data/lib/hanami/utils/query_string.rb +1 -1
- data/lib/hanami/utils/shell_color.rb +9 -9
- data/lib/hanami/utils/string.rb +44 -470
- data/lib/hanami/utils/version.rb +3 -1
- metadata +30 -16
- data/lib/hanami/utils/duplicable.rb +0 -80
- data/lib/hanami/utils/inflector.rb +0 -494
@@ -14,9 +14,9 @@ module Hanami
|
|
14
14
|
# @api private
|
15
15
|
def call(app, severity, datetime, _progname)
|
16
16
|
::Hash[
|
17
|
-
app:
|
17
|
+
app: app,
|
18
18
|
severity: severity,
|
19
|
-
time:
|
19
|
+
time: datetime,
|
20
20
|
]
|
21
21
|
end
|
22
22
|
end
|
@@ -44,9 +44,9 @@ module Hanami
|
|
44
44
|
# @return [::Hash] an Hash containing the keys `:app`, `:severity`, and `:time`
|
45
45
|
def call(app, severity, datetime, _progname)
|
46
46
|
::Hash[
|
47
|
-
app:
|
47
|
+
app: app(app),
|
48
48
|
severity: severity(severity),
|
49
|
-
time:
|
49
|
+
time: datetime(datetime),
|
50
50
|
]
|
51
51
|
end
|
52
52
|
|
@@ -57,18 +57,18 @@ module Hanami
|
|
57
57
|
# @since 1.2.0
|
58
58
|
# @api private
|
59
59
|
COLORS = ::Hash[
|
60
|
-
app:
|
60
|
+
app: :blue,
|
61
61
|
datetime: :cyan,
|
62
62
|
].freeze
|
63
63
|
|
64
64
|
# @since 1.2.0
|
65
65
|
# @api private
|
66
66
|
LEVELS = ::Hash[
|
67
|
-
Hanami::Logger::DEBUG
|
68
|
-
Hanami::Logger::INFO
|
69
|
-
Hanami::Logger::WARN
|
70
|
-
Hanami::Logger::ERROR
|
71
|
-
Hanami::Logger::FATAL
|
67
|
+
Hanami::Logger::DEBUG => :cyan,
|
68
|
+
Hanami::Logger::INFO => :magenta,
|
69
|
+
Hanami::Logger::WARN => :yellow,
|
70
|
+
Hanami::Logger::ERROR => :red,
|
71
|
+
Hanami::Logger::FATAL => :red,
|
72
72
|
Hanami::Logger::UNKNOWN => :blue,
|
73
73
|
].freeze
|
74
74
|
|
data/lib/hanami/logger/filter.rb
CHANGED
@@ -9,21 +9,19 @@ module Hanami
|
|
9
9
|
# @since 1.1.0
|
10
10
|
# @api private
|
11
11
|
class Filter
|
12
|
-
# @since 1.
|
12
|
+
# @since 1.3.7
|
13
13
|
# @api private
|
14
|
-
|
14
|
+
FILTERED_VALUE = "[FILTERED]"
|
15
|
+
|
16
|
+
def initialize(filters = [], mask: FILTERED_VALUE)
|
15
17
|
@filters = filters
|
18
|
+
@mask = mask
|
16
19
|
end
|
17
20
|
|
18
21
|
# @since 1.1.0
|
19
22
|
# @api private
|
20
|
-
def call(
|
21
|
-
|
22
|
-
*keys, last = _actual_keys(hash, key.split("."))
|
23
|
-
keys.inject(hash, :fetch)[last] = "[FILTERED]"
|
24
|
-
end
|
25
|
-
|
26
|
-
hash
|
23
|
+
def call(params)
|
24
|
+
_filter(_copy_params(params))
|
27
25
|
end
|
28
26
|
|
29
27
|
private
|
@@ -32,6 +30,29 @@ module Hanami
|
|
32
30
|
# @api private
|
33
31
|
attr_reader :filters
|
34
32
|
|
33
|
+
# @since 1.3.7
|
34
|
+
# @api private
|
35
|
+
attr_reader :mask
|
36
|
+
|
37
|
+
# This is a simple deep merge to merge the original input
|
38
|
+
# with the filtered hash which contains '[FILTERED]' string.
|
39
|
+
#
|
40
|
+
# It only deep-merges if the conflict values are both hashes.
|
41
|
+
#
|
42
|
+
# @since 1.3.7
|
43
|
+
# @api private
|
44
|
+
def _deep_merge(original_hash, filtered_hash)
|
45
|
+
original_hash.merge(filtered_hash) do |_key, original_item, filtered_item|
|
46
|
+
if original_item.is_a?(Hash) && filtered_item.is_a?(Hash)
|
47
|
+
_deep_merge(original_item, filtered_item)
|
48
|
+
elsif filtered_item == FILTERED_VALUE
|
49
|
+
filtered_item
|
50
|
+
else
|
51
|
+
original_item
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
35
56
|
# @since 1.1.0
|
36
57
|
# @api private
|
37
58
|
def _filtered_keys(hash)
|
@@ -74,6 +95,50 @@ module Hanami
|
|
74
95
|
def _key_paths?(value)
|
75
96
|
value.is_a?(Enumerable) && !value.is_a?(File)
|
76
97
|
end
|
98
|
+
|
99
|
+
# @since 1.3.7
|
100
|
+
# @api private
|
101
|
+
def _deep_dup(hash)
|
102
|
+
hash.transform_values do |value|
|
103
|
+
if value.is_a?(Hash)
|
104
|
+
_deep_dup(value)
|
105
|
+
else
|
106
|
+
_key_paths?(value) ? value.dup : value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# @since 1.3.7
|
112
|
+
# @api private
|
113
|
+
def _copy_params(params)
|
114
|
+
case params
|
115
|
+
when Hash
|
116
|
+
_deep_dup(params)
|
117
|
+
when Array
|
118
|
+
params.map { |hash| _deep_dup(hash) }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# @since 1.3.7
|
123
|
+
# @api private
|
124
|
+
def _filter_hash(hash)
|
125
|
+
_filtered_keys(hash).each do |key|
|
126
|
+
*keys, last = _actual_keys(hash, key.split("."))
|
127
|
+
keys.inject(hash, :fetch)[last] = mask
|
128
|
+
end
|
129
|
+
hash
|
130
|
+
end
|
131
|
+
|
132
|
+
# @since 1.3.7
|
133
|
+
# @api private
|
134
|
+
def _filter(params)
|
135
|
+
case params
|
136
|
+
when Hash
|
137
|
+
_filter_hash(params)
|
138
|
+
when Array
|
139
|
+
params.map { |hash| _filter_hash(hash) }
|
140
|
+
end
|
141
|
+
end
|
77
142
|
end
|
78
143
|
end
|
79
144
|
end
|
@@ -103,25 +103,25 @@ module Hanami
|
|
103
103
|
|
104
104
|
# @since 0.8.0
|
105
105
|
# @api private
|
106
|
-
def _message_hash(message)
|
106
|
+
def _message_hash(message)
|
107
107
|
case message
|
108
|
-
when Hash
|
108
|
+
when ::Hash
|
109
109
|
@filter.call(message)
|
110
110
|
when Exception
|
111
|
-
Hash[
|
112
|
-
message:
|
111
|
+
::Hash[
|
112
|
+
message: message.message,
|
113
113
|
backtrace: message.backtrace || [],
|
114
|
-
error:
|
114
|
+
error: message.class
|
115
115
|
]
|
116
116
|
else
|
117
|
-
Hash[message: message]
|
117
|
+
::Hash[message: message]
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
121
|
# @since 0.8.0
|
122
122
|
# @api private
|
123
123
|
def _format(hash)
|
124
|
-
"#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}"
|
124
|
+
"#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}" # rubocop:disable Layout/LineLength
|
125
125
|
end
|
126
126
|
|
127
127
|
# @since 1.2.0
|
data/lib/hanami/utils.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
2
4
|
|
3
5
|
# Hanami - The web, with simplicity
|
4
6
|
#
|
5
7
|
# @since 0.1.0
|
6
8
|
module Hanami
|
7
|
-
require
|
8
|
-
require
|
9
|
+
require "hanami/utils/version"
|
10
|
+
require "hanami/utils/file_list"
|
9
11
|
|
10
12
|
# Ruby core extentions and Hanami utilities
|
11
13
|
#
|
@@ -13,15 +15,15 @@ module Hanami
|
|
13
15
|
module Utils
|
14
16
|
# @since 0.3.1
|
15
17
|
# @api private
|
16
|
-
HANAMI_JRUBY =
|
18
|
+
HANAMI_JRUBY = "java"
|
17
19
|
|
18
20
|
# @since 0.3.1
|
19
21
|
# @api private
|
20
|
-
HANAMI_RUBINIUS =
|
22
|
+
HANAMI_RUBINIUS = "rbx"
|
21
23
|
|
22
24
|
# Checks if the current VM is JRuby
|
23
25
|
#
|
24
|
-
# @return [TrueClass,FalseClass]
|
26
|
+
# @return [TrueClass,FalseClass] info whether the VM is JRuby or not
|
25
27
|
#
|
26
28
|
# @since 0.3.1
|
27
29
|
# @api private
|
@@ -31,7 +33,7 @@ module Hanami
|
|
31
33
|
|
32
34
|
# Checks if the current VM is Rubinius
|
33
35
|
#
|
34
|
-
# @return [TrueClass,FalseClass]
|
36
|
+
# @return [TrueClass,FalseClass] info whether the VM is Rubinius or not
|
35
37
|
#
|
36
38
|
# @since 0.3.1
|
37
39
|
# @api private
|
@@ -39,7 +41,7 @@ module Hanami
|
|
39
41
|
RUBY_ENGINE == HANAMI_RUBINIUS
|
40
42
|
end
|
41
43
|
|
42
|
-
# Recursively
|
44
|
+
# Recursively requires Ruby files under the given directory.
|
43
45
|
#
|
44
46
|
# If the directory is relative, it implies it's the path from current directory.
|
45
47
|
# If the directory is absolute, it uses as it is.
|
@@ -54,22 +56,6 @@ module Hanami
|
|
54
56
|
for_each_file_in(directory) { |file| require_relative(file) }
|
55
57
|
end
|
56
58
|
|
57
|
-
# Recursively reload Ruby files under the given directory.
|
58
|
-
#
|
59
|
-
# If the directory is relative, it implies it's the path from current directory.
|
60
|
-
# If the directory is absolute, it uses as it is.
|
61
|
-
#
|
62
|
-
# It respects file separator of the current operating system.
|
63
|
-
# A pattern like <tt>"path/to/files"</tt> will work both on *NIX and Windows machines.
|
64
|
-
#
|
65
|
-
# @param directory [String, Pathname] the directory
|
66
|
-
#
|
67
|
-
# @since 1.0.0
|
68
|
-
# @api private
|
69
|
-
def self.reload!(directory)
|
70
|
-
for_each_file_in(directory) { |file| load(file) }
|
71
|
-
end
|
72
|
-
|
73
59
|
# Recursively scans through the given directory and yields the given block
|
74
60
|
# for each Ruby source file.
|
75
61
|
#
|
@@ -85,9 +71,9 @@ module Hanami
|
|
85
71
|
# @since 1.0.0
|
86
72
|
# @api private
|
87
73
|
def self.for_each_file_in(directory, &blk)
|
88
|
-
directory = directory.to_s.gsub(%r{(
|
74
|
+
directory = directory.to_s.gsub(%r{(/|\\)}, File::SEPARATOR)
|
89
75
|
directory = Pathname.new(Dir.pwd).join(directory).to_s
|
90
|
-
directory = File.join(directory,
|
76
|
+
directory = File.join(directory, "**", "*.rb") unless directory =~ /(\*\*)/
|
91
77
|
|
92
78
|
FileList[directory].each(&blk)
|
93
79
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hanami
|
2
4
|
module Utils
|
3
5
|
# BasicObject
|
4
6
|
#
|
5
7
|
# @since 0.3.5
|
6
8
|
class BasicObject < ::BasicObject
|
7
|
-
#
|
9
|
+
# Lookups constants at the top-level namespace, if they are missing in the
|
8
10
|
# current context.
|
9
11
|
#
|
10
12
|
# @param name [Symbol] the constant name
|
@@ -21,7 +23,7 @@ module Hanami
|
|
21
23
|
::Object.const_get(name)
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
26
|
+
# Returns the class for debugging purposes.
|
25
27
|
#
|
26
28
|
# @since 0.3.5
|
27
29
|
#
|
@@ -38,17 +40,15 @@ module Hanami
|
|
38
40
|
#
|
39
41
|
# @see http://ruby-doc.org/core/Object.html#method-i-inspect
|
40
42
|
#
|
41
|
-
# rubocop:disable Style/FormatString
|
42
43
|
# rubocop:disable Style/FormatStringToken
|
43
44
|
def inspect
|
44
45
|
"#<#{self.class}:#{'0x0000%x' % (__id__ << 1)}#{__inspect}>"
|
45
46
|
end
|
46
47
|
# rubocop:enable Style/FormatStringToken
|
47
|
-
# rubocop:enable Style/FormatString
|
48
48
|
|
49
49
|
# @!macro [attach] instance_of?(class)
|
50
50
|
#
|
51
|
-
#
|
51
|
+
# Determines if self is an instance of given class or module
|
52
52
|
#
|
53
53
|
# @param class [Class,Module] the class of module to verify
|
54
54
|
#
|
@@ -63,7 +63,7 @@ module Hanami
|
|
63
63
|
|
64
64
|
# @!macro [attach] is_a?(class)
|
65
65
|
#
|
66
|
-
#
|
66
|
+
# Determines if self is of the type of the object class or module
|
67
67
|
#
|
68
68
|
# @param class [Class,Module] the class of module to verify
|
69
69
|
#
|
@@ -78,7 +78,7 @@ module Hanami
|
|
78
78
|
|
79
79
|
# @!macro [attach] kind_of?(class)
|
80
80
|
#
|
81
|
-
#
|
81
|
+
# Determines if self is of the kind of the object class or module
|
82
82
|
#
|
83
83
|
# @param class [Class,Module] the class of module to verify
|
84
84
|
#
|
data/lib/hanami/utils/blank.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Hanami
|
2
4
|
module Utils
|
3
5
|
# Checks for blank
|
@@ -11,7 +13,7 @@ module Hanami
|
|
11
13
|
# @api private
|
12
14
|
STRING_MATCHER = /\A[[:space:]]*\z/.freeze
|
13
15
|
|
14
|
-
# Checks object is blank
|
16
|
+
# Checks if object is blank
|
15
17
|
#
|
16
18
|
# @example Basic Usage
|
17
19
|
# require 'hanami/utils/blank'
|
@@ -19,21 +21,20 @@ module Hanami
|
|
19
21
|
# Hanami::Utils::Blank.blank?(Hanami::Utils::String.new('')) # => true
|
20
22
|
# Hanami::Utils::Blank.blank?(' ') # => true
|
21
23
|
# Hanami::Utils::Blank.blank?(nil) # => true
|
22
|
-
# Hanami::Utils::Blank.blank?(Hanami::Utils::Hash.new({})) # => true
|
23
24
|
# Hanami::Utils::Blank.blank?(true) # => false
|
24
25
|
# Hanami::Utils::Blank.blank?(1) # => false
|
25
26
|
#
|
26
27
|
# @param object the argument
|
27
28
|
#
|
28
|
-
# @return [TrueClass,FalseClass]
|
29
|
+
# @return [TrueClass,FalseClass] info, whether object is blank
|
29
30
|
#
|
30
31
|
# @since 0.8.0
|
31
32
|
# @api private
|
32
|
-
def self.blank?(object)
|
33
|
+
def self.blank?(object)
|
33
34
|
case object
|
34
35
|
when String, ::String
|
35
|
-
STRING_MATCHER === object
|
36
|
-
when
|
36
|
+
STRING_MATCHER === object
|
37
|
+
when ::Hash, ::Array
|
37
38
|
object.empty?
|
38
39
|
when TrueClass, Numeric
|
39
40
|
false
|
@@ -44,7 +45,7 @@ module Hanami
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
# Checks object is filled
|
48
|
+
# Checks if object is filled
|
48
49
|
#
|
49
50
|
# @example Basic Usage
|
50
51
|
# require 'hanami/utils/blank'
|
@@ -54,11 +55,10 @@ module Hanami
|
|
54
55
|
# Hanami::Utils::Blank.filled?(Hanami::Utils::String.new('')) # => false
|
55
56
|
# Hanami::Utils::Blank.filled?(' ') # => false
|
56
57
|
# Hanami::Utils::Blank.filled?(nil) # => false
|
57
|
-
# Hanami::Utils::Blank.filled?(Hanami::Utils::Hash.new({})) # => false
|
58
58
|
#
|
59
59
|
# @param object the argument
|
60
60
|
#
|
61
|
-
# @return [TrueClass,FalseClass]
|
61
|
+
# @return [TrueClass,FalseClass] whether the object is filled
|
62
62
|
#
|
63
63
|
# @since 1.0.0
|
64
64
|
# @api private
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/array"
|
4
|
+
|
1
5
|
module Hanami
|
2
6
|
module Utils
|
3
7
|
# Before and After callbacks
|
@@ -10,13 +14,13 @@ module Hanami
|
|
10
14
|
# @since 0.1.0
|
11
15
|
# @private
|
12
16
|
class Chain
|
13
|
-
#
|
17
|
+
# Returns a new chain
|
14
18
|
#
|
15
19
|
# @return [Hanami::Utils::Callbacks::Chain]
|
16
20
|
#
|
17
21
|
# @since 0.2.0
|
18
22
|
def initialize
|
19
|
-
@chain =
|
23
|
+
@chain = Concurrent::Array.new
|
20
24
|
end
|
21
25
|
|
22
26
|
# Appends the given callbacks to the end of the chain.
|
@@ -148,6 +152,17 @@ module Hanami
|
|
148
152
|
end
|
149
153
|
end
|
150
154
|
|
155
|
+
# Return a duplicate callbacks chain
|
156
|
+
#
|
157
|
+
# @return [Hanami::Utils::Callbacks] the duplicated chain
|
158
|
+
#
|
159
|
+
# @since 2.0.0
|
160
|
+
def dup
|
161
|
+
super.tap do |instance|
|
162
|
+
instance.instance_variable_set(:@chain, instance.chain.dup)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
151
166
|
# It freezes the object by preventing further modifications.
|
152
167
|
#
|
153
168
|
# @since 0.2.0
|
@@ -168,6 +183,10 @@ module Hanami
|
|
168
183
|
@chain.freeze
|
169
184
|
end
|
170
185
|
|
186
|
+
protected
|
187
|
+
|
188
|
+
attr_reader :chain
|
189
|
+
|
171
190
|
private
|
172
191
|
|
173
192
|
# @api private
|
@@ -248,7 +267,9 @@ module Hanami
|
|
248
267
|
end
|
249
268
|
|
250
269
|
# Method callback
|
251
|
-
#
|
270
|
+
#
|
271
|
+
# It wraps a symbol or a string representing a method name that is
|
272
|
+
# implemented by the context within it will be called.
|
252
273
|
#
|
253
274
|
# @since 0.1.0
|
254
275
|
# @api private
|