hanami-utils 1.3.7 → 2.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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) # rubocop:disable Metrics/MethodLength
107
107
  case message
108
- when Hash
108
+ when ::Hash
109
109
  @filter.call(message)
110
110
  when Exception
111
- Hash[
112
- message: message.message,
111
+ ::Hash[
112
+ message: message.message,
113
113
  backtrace: message.backtrace || [],
114
- error: message.class
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)}" # rubocop:disable Layout/LineLength
124
+ "#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}"
125
125
  end
126
126
 
127
127
  # @since 1.2.0
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Middleware
5
+ # Hanami middleware utils
6
+
7
+ # @since 2.0.0
8
+ class Error < ::StandardError
9
+ end
10
+ end
11
+ end
@@ -23,7 +23,7 @@ module Hanami
23
23
 
24
24
  # Checks if the current VM is JRuby
25
25
  #
26
- # @return [TrueClass,FalseClass] info whether the VM is JRuby or not
26
+ # @return [TrueClass,FalseClass] return if the VM is JRuby or not
27
27
  #
28
28
  # @since 0.3.1
29
29
  # @api private
@@ -33,7 +33,7 @@ module Hanami
33
33
 
34
34
  # Checks if the current VM is Rubinius
35
35
  #
36
- # @return [TrueClass,FalseClass] info whether the VM is Rubinius or not
36
+ # @return [TrueClass,FalseClass] return if the VM is Rubinius or not
37
37
  #
38
38
  # @since 0.3.1
39
39
  # @api private
@@ -41,7 +41,7 @@ module Hanami
41
41
  RUBY_ENGINE == HANAMI_RUBINIUS
42
42
  end
43
43
 
44
- # Recursively requires Ruby files under the given directory.
44
+ # Recursively require Ruby files under the given directory.
45
45
  #
46
46
  # If the directory is relative, it implies it's the path from current directory.
47
47
  # If the directory is absolute, it uses as it is.
@@ -56,22 +56,6 @@ module Hanami
56
56
  for_each_file_in(directory) { |file| require_relative(file) }
57
57
  end
58
58
 
59
- # Recursively reloads Ruby files under the given directory.
60
- #
61
- # If the directory is relative, it implies it's the path from current directory.
62
- # If the directory is absolute, it uses as it is.
63
- #
64
- # It respects file separator of the current operating system.
65
- # A pattern like <tt>"path/to/files"</tt> will work both on *NIX and Windows machines.
66
- #
67
- # @param directory [String, Pathname] the directory
68
- #
69
- # @since 1.0.0
70
- # @api private
71
- def self.reload!(directory)
72
- for_each_file_in(directory) { |file| load(file) }
73
- end
74
-
75
59
  # Recursively scans through the given directory and yields the given block
76
60
  # for each Ruby source file.
77
61
  #
@@ -6,24 +6,7 @@ module Hanami
6
6
  #
7
7
  # @since 0.3.5
8
8
  class BasicObject < ::BasicObject
9
- # Lookups constants at the top-level namespace, if they are missing in the
10
- # current context.
11
- #
12
- # @param name [Symbol] the constant name
13
- #
14
- # @return [Object, Module] the constant
15
- #
16
- # @raise [NameError] if the constant cannot be found
17
- #
18
- # @since 1.3.4
19
- # @api private
20
- #
21
- # @see https://ruby-doc.org/core/Module.html#method-i-const_missing
22
- def self.const_missing(name)
23
- ::Object.const_get(name)
24
- end
25
-
26
- # Returns the class for debugging purposes.
9
+ # Return the class for debugging purposes.
27
10
  #
28
11
  # @since 0.3.5
29
12
  #
@@ -40,56 +23,13 @@ module Hanami
40
23
  #
41
24
  # @see http://ruby-doc.org/core/Object.html#method-i-inspect
42
25
  #
26
+ # rubocop:disable Style/FormatString
43
27
  # rubocop:disable Style/FormatStringToken
44
28
  def inspect
45
29
  "#<#{self.class}:#{'0x0000%x' % (__id__ << 1)}#{__inspect}>"
46
30
  end
47
31
  # rubocop:enable Style/FormatStringToken
48
-
49
- # @!macro [attach] instance_of?(class)
50
- #
51
- # Determines if self is an instance of given class or module
52
- #
53
- # @param class [Class,Module] the class of module to verify
54
- #
55
- # @return [TrueClass,FalseClass] the result of the check
56
- #
57
- # @raise [TypeError] if the given argument is not of the expected types
58
- #
59
- # @since 1.3.2
60
- #
61
- # @see http://ruby-doc.org/core/Object.html#method-i-instance_of-3F
62
- define_method :instance_of?, ::Object.instance_method(:instance_of?)
63
-
64
- # @!macro [attach] is_a?(class)
65
- #
66
- # Determines if self is of the type of the object class or module
67
- #
68
- # @param class [Class,Module] the class of module to verify
69
- #
70
- # @return [TrueClass,FalseClass] the result of the check
71
- #
72
- # @raise [TypeError] if the given argument is not of the expected types
73
- #
74
- # @since 1.3.2
75
- #
76
- # @see http://ruby-doc.org/core/Object.html#method-i-is_a-3F
77
- define_method :is_a?, ::Object.instance_method(:is_a?)
78
-
79
- # @!macro [attach] kind_of?(class)
80
- #
81
- # Determines if self is of the kind of the object class or module
82
- #
83
- # @param class [Class,Module] the class of module to verify
84
- #
85
- # @return [TrueClass,FalseClass] the result of the check
86
- #
87
- # @raise [TypeError] if the given argument is not of the expected types
88
- #
89
- # @since 1.3.2
90
- #
91
- # @see http://ruby-doc.org/core/Object.html#method-i-kind_of-3F
92
- define_method :kind_of?, ::Object.instance_method(:kind_of?)
32
+ # rubocop:enable Style/FormatString
93
33
 
94
34
  # Alias for __id__
95
35
  #
@@ -13,7 +13,7 @@ module Hanami
13
13
  # @api private
14
14
  STRING_MATCHER = /\A[[:space:]]*\z/.freeze
15
15
 
16
- # Checks if object is blank
16
+ # Checks object is blank
17
17
  #
18
18
  # @example Basic Usage
19
19
  # require 'hanami/utils/blank'
@@ -21,21 +21,20 @@ module Hanami
21
21
  # Hanami::Utils::Blank.blank?(Hanami::Utils::String.new('')) # => true
22
22
  # Hanami::Utils::Blank.blank?(' ') # => true
23
23
  # Hanami::Utils::Blank.blank?(nil) # => true
24
- # Hanami::Utils::Blank.blank?(Hanami::Utils::Hash.new({})) # => true
25
24
  # Hanami::Utils::Blank.blank?(true) # => false
26
25
  # Hanami::Utils::Blank.blank?(1) # => false
27
26
  #
28
27
  # @param object the argument
29
28
  #
30
- # @return [TrueClass,FalseClass] info, whether object is blank
29
+ # @return [TrueClass,FalseClass]
31
30
  #
32
31
  # @since 0.8.0
33
32
  # @api private
34
- def self.blank?(object)
33
+ def self.blank?(object) # rubocop:disable Metrics/MethodLength
35
34
  case object
36
35
  when String, ::String
37
36
  STRING_MATCHER === object # rubocop:disable Style/CaseEquality
38
- when Hash, ::Hash, ::Array
37
+ when ::Hash, ::Array
39
38
  object.empty?
40
39
  when TrueClass, Numeric
41
40
  false
@@ -46,7 +45,7 @@ module Hanami
46
45
  end
47
46
  end
48
47
 
49
- # Checks if object is filled
48
+ # Checks object is filled
50
49
  #
51
50
  # @example Basic Usage
52
51
  # require 'hanami/utils/blank'
@@ -56,11 +55,10 @@ module Hanami
56
55
  # Hanami::Utils::Blank.filled?(Hanami::Utils::String.new('')) # => false
57
56
  # Hanami::Utils::Blank.filled?(' ') # => false
58
57
  # Hanami::Utils::Blank.filled?(nil) # => false
59
- # Hanami::Utils::Blank.filled?(Hanami::Utils::Hash.new({})) # => false
60
58
  #
61
59
  # @param object the argument
62
60
  #
63
- # @return [TrueClass,FalseClass] whether the object is filled
61
+ # @return [TrueClass,FalseClass]
64
62
  #
65
63
  # @since 1.0.0
66
64
  # @api private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "concurrent/array"
4
+
3
5
  module Hanami
4
6
  module Utils
5
7
  # Before and After callbacks
@@ -12,13 +14,13 @@ module Hanami
12
14
  # @since 0.1.0
13
15
  # @private
14
16
  class Chain
15
- # Returns a new chain
17
+ # Return a new chain
16
18
  #
17
19
  # @return [Hanami::Utils::Callbacks::Chain]
18
20
  #
19
21
  # @since 0.2.0
20
22
  def initialize
21
- @chain = []
23
+ @chain = Concurrent::Array.new
22
24
  end
23
25
 
24
26
  # Appends the given callbacks to the end of the chain.
@@ -150,6 +152,17 @@ module Hanami
150
152
  end
151
153
  end
152
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
+
153
166
  # It freezes the object by preventing further modifications.
154
167
  #
155
168
  # @since 0.2.0
@@ -170,6 +183,10 @@ module Hanami
170
183
  @chain.freeze
171
184
  end
172
185
 
186
+ protected
187
+
188
+ attr_reader :chain
189
+
173
190
  private
174
191
 
175
192
  # @api private
@@ -250,9 +267,7 @@ module Hanami
250
267
  end
251
268
 
252
269
  # Method callback
253
- #
254
- # It wraps a symbol or a string representing a method name that is
255
- # implemented by the context within it will be called.
270
+ # It wraps a symbol or a string representing a method name that is implemented by the context within it will be called.
256
271
  #
257
272
  # @since 0.1.0
258
273
  # @api private
@@ -74,59 +74,9 @@ module Hanami
74
74
  load!(name, namespace) if namespace.const_defined?(name.to_s, false)
75
75
  end
76
76
 
77
- # Loads a class from the given pattern name and namespace
78
- #
79
- # @param pattern [String] the class name pattern
80
- # @param namespace [Class, Module] the Ruby namespace where we want to perform the lookup.
81
- # @return [Class, Module] the found Ruby constant.
82
- #
83
- # @raise [NameError] if no constant can be found.
84
- #
85
- # @since 0.3.1
86
- #
87
- # @see Hanami::Utils::String#tokenize
88
- #
89
- # @example
90
- # require 'hanami/utils/class'
91
- #
92
- # module App
93
- # module Service
94
- # class Endpoint
95
- # end
96
- # end
97
- #
98
- # class ServiceEndpoint
99
- # end
100
- # end
101
- #
102
- # # basic usage
103
- # Hanami::Utils::Class.load_from_pattern!('App::Service') # => App::Service
104
- #
105
- # # with explicit namespace
106
- # Hanami::Utils::Class.load_from_pattern!('Service', App) # => App::Service
107
- #
108
- # # with pattern
109
- # Hanami::Utils::Class.load_from_pattern!('App::Service(::Endpoint|Endpoint)') # => App::Service::Endpoint
110
- # Hanami::Utils::Class.load_from_pattern!('App::Service(Endpoint|::Endpoint)') # => App::ServiceEndpoint
111
- #
112
- # # with missing constant
113
- # Hanami::Utils::Class.load_from_pattern!('Unknown') # => raises NameError
114
- def self.load_from_pattern!(pattern, namespace = Object)
115
- Deprecation.new("Hanami::Utils::Class.load_from_pattern! is deprecated, please use Hanami::Utils::Class.load! instead") # rubocop:disable Layout/LineLength
116
-
117
- tokenize(pattern) do |token|
118
- begin
119
- return namespace.const_get(token, false)
120
- rescue NameError # rubocop:disable Lint/SuppressedException
121
- end
122
- end
123
-
124
- full_name = [(namespace == Object ? nil : namespace), pattern].compact.join("::")
125
- raise NameError.new("uninitialized constant #{full_name}")
126
- end
127
-
77
+ # rubocop:disable Metrics/MethodLength
128
78
  def self.tokenize(pattern)
129
- if match = TOKENIZE_REGEXP.match(pattern)
79
+ if match = TOKENIZE_REGEXP.match(pattern) # rubocop:disable Lint/AssignmentInCondition
130
80
  pre = match.pre_match
131
81
  post = match.post_match
132
82
  tokens = match[1].split(TOKENIZE_SEPARATOR)
@@ -139,6 +89,7 @@ module Hanami
139
89
 
140
90
  nil
141
91
  end
92
+ # rubocop:enable Metrics/MethodLength
142
93
 
143
94
  # Regexp for .tokenize
144
95
  #
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
- require "hanami/utils/duplicable"
5
-
6
3
  module Hanami
7
4
  module Utils
8
5
  # Inheritable class level variable accessors.
@@ -10,6 +7,8 @@ module Hanami
10
7
  #
11
8
  # @see Hanami::Utils::ClassAttribute::ClassMethods
12
9
  module ClassAttribute
10
+ require "hanami/utils/class_attribute/attributes"
11
+
13
12
  # @api private
14
13
  def self.included(base)
15
14
  base.extend ClassMethods
@@ -18,6 +17,12 @@ module Hanami
18
17
  # @since 0.1.0
19
18
  # @api private
20
19
  module ClassMethods
20
+ def self.extended(base)
21
+ base.class_eval do
22
+ @__class_attributes = Attributes.new unless defined?(@__class_attributes)
23
+ end
24
+ end
25
+
21
26
  # Defines a class level accessor for the given attribute(s).
22
27
  #
23
28
  # A value set for a superclass is automatically available by their
@@ -68,11 +73,17 @@ module Hanami
68
73
  # SmallAirplane.engines # => 2
69
74
  # SmallAirplane.wheels # => 8
70
75
  def class_attribute(*attributes)
71
- singleton_class.class_eval do
72
- attr_accessor(*attributes)
73
- end
76
+ attributes.each do |attr|
77
+ singleton_class.class_eval %(
78
+ def #{attr}
79
+ class_attributes[:#{attr}]
80
+ end
74
81
 
75
- class_attributes.merge(attributes)
82
+ def #{attr}=(value)
83
+ class_attributes[:#{attr}] = value
84
+ end
85
+ ), __FILE__, __LINE__ - 8
86
+ end
76
87
  end
77
88
 
78
89
  protected
@@ -80,11 +91,9 @@ module Hanami
80
91
  # @see Class#inherited
81
92
  # @api private
82
93
  def inherited(subclass)
83
- class_attributes.each do |attr|
84
- value = send(attr)
85
- value = Duplicable.dup(value)
86
- subclass.class_attribute attr
87
- subclass.send("#{attr}=", value)
94
+ ca = class_attributes.dup
95
+ subclass.class_eval do
96
+ @__class_attributes = ca
88
97
  end
89
98
 
90
99
  super
@@ -95,7 +104,7 @@ module Hanami
95
104
  # Class accessor for class attributes.
96
105
  # @api private
97
106
  def class_attributes
98
- @class_attributes ||= Set.new
107
+ @__class_attributes
99
108
  end
100
109
  end
101
110
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent/map"
4
+
5
+ module Hanami
6
+ module Utils
7
+ module ClassAttribute
8
+ # Class attributes set
9
+ #
10
+ # @since 2.0.0
11
+ # @api private
12
+ class Attributes
13
+ # @since 2.0.0
14
+ # @api private
15
+ def initialize(attributes: Concurrent::Map.new)
16
+ @attributes = attributes
17
+ end
18
+
19
+ # @since 2.0.0
20
+ # @api private
21
+ def []=(key, value)
22
+ @attributes[key.to_sym] = value
23
+ end
24
+
25
+ # @since 2.0.0
26
+ # @api private
27
+ def [](key)
28
+ @attributes.fetch(key, nil)
29
+ end
30
+
31
+ # @since 2.0.0
32
+ # @api private
33
+ def dup
34
+ attributes = Concurrent::Map.new.tap do |attrs|
35
+ @attributes.each do |key, value|
36
+ attrs[key.to_sym] = value.dup
37
+ end
38
+ end
39
+
40
+ self.class.new(attributes: attributes)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end