/
class.rb
156 lines (147 loc) · 4.78 KB
/
class.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
require 'hanami/utils/deprecation'
module Hanami
module Utils
# Class utilities
# @since 0.1.0
class Class
# Loads a class for the given name.
#
# @param name [String, Class] the specific class name
# @param namespace [Class, Module] the Ruby namespace where we want to perform the lookup.
# @return [Class, Module] the found Ruby constant.
#
# @raise [NameError] if no constant can be found.
#
# @since 0.1.0
#
# @example
# require 'hanami/utils/class'
#
# module App
# module Service
# class Endpoint
# end
# end
#
# class ServiceEndpoint
# end
# end
#
# # basic usage
# Hanami::Utils::Class.load!('App::Service') # => App::Service
# Hanami::Utils::Class.load!(App::Service) # => App::Service
#
# # with explicit namespace
# Hanami::Utils::Class.load!('Service', App) # => App::Service
#
# # with missing constant
# Hanami::Utils::Class.load!('Unknown') # => raises NameError
def self.load!(name, namespace = Object)
namespace.const_get(name.to_s, false)
end
# Loads a class for the given name, only if it's defined.
#
# @param name [String, Class] the specific class name
# @param namespace [Class, Module] the Ruby namespace where we want to perform the lookup.
# @return [Class, Module, NilClass] the Ruby constant, or nil if not found.
#
# @since 0.8.0
#
# @example
# require 'hanami/utils/class'
#
# module App
# module Service
# class Endpoint
# end
# end
#
# class ServiceEndpoint
# end
# end
#
# # basic usage
# Hanami::Utils::Class.load('App::Service') # => App::Service
# Hanami::Utils::Class.load(App::Service) # => App::Service
#
# # with explicit namespace
# Hanami::Utils::Class.load('Service', App) # => App::Service
def self.load(name, namespace = Object)
load!(name, namespace) if namespace.const_defined?(name.to_s, false)
end
# Loads a class from the given pattern name and namespace
#
# @param pattern [String] the class name pattern
# @param namespace [Class, Module] the Ruby namespace where we want to perform the lookup.
# @return [Class, Module] the found Ruby constant.
#
# @raise [NameError] if no constant can be found.
#
# @since 0.3.1
#
# @see Hanami::Utils::String#tokenize
#
# @example
# require 'hanami/utils/class'
#
# module App
# module Service
# class Endpoint
# end
# end
#
# class ServiceEndpoint
# end
# end
#
# # basic usage
# Hanami::Utils::Class.load_from_pattern!('App::Service') # => App::Service
#
# # with explicit namespace
# Hanami::Utils::Class.load_from_pattern!('Service', App) # => App::Service
#
# # with pattern
# Hanami::Utils::Class.load_from_pattern!('App::Service(::Endpoint|Endpoint)') # => App::Service::Endpoint
# Hanami::Utils::Class.load_from_pattern!('App::Service(Endpoint|::Endpoint)') # => App::ServiceEndpoint
#
# # with missing constant
# Hanami::Utils::Class.load_from_pattern!('Unknown') # => raises NameError
def self.load_from_pattern!(pattern, namespace = Object)
Deprecation.new('Hanami::Utils::Class.load_from_pattern! is deprecated, please use Hanami::Utils::Class.load! instead')
tokenize(pattern) do |token|
begin
return namespace.const_get(token, false)
rescue NameError # rubocop:disable Lint/SuppressedException
end
end
full_name = [(namespace == Object ? nil : namespace), pattern].compact.join('::')
raise NameError.new("uninitialized constant #{full_name}")
end
# rubocop:disable Metrics/MethodLength
def self.tokenize(pattern)
if match = TOKENIZE_REGEXP.match(pattern) # rubocop:disable Lint/AssignmentInCondition
pre = match.pre_match
post = match.post_match
tokens = match[1].split(TOKENIZE_SEPARATOR)
tokens.each do |token|
yield("#{pre}#{token}#{post}")
end
else
yield(pattern)
end
nil
end
# rubocop:enable Metrics/MethodLength
# Regexp for .tokenize
#
# @since 1.3.0
# @api private
TOKENIZE_REGEXP = /\((.*)\)/.freeze
# Separator for .tokenize
#
# @since 1.3.0
# @api private
TOKENIZE_SEPARATOR = '|'.freeze
end
end
end