pakyow-support 0.11.3 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{pakyow-support/CHANGELOG.md → CHANGELOG.md} +4 -0
- data/LICENSE +4 -0
- data/{pakyow-support/README.md → README.md} +1 -2
- data/lib/pakyow/support/aargv.rb +25 -0
- data/lib/pakyow/support/bindable.rb +19 -0
- data/lib/pakyow/support/class_state.rb +49 -0
- data/lib/pakyow/support/cli/runner.rb +106 -0
- data/lib/pakyow/support/cli/style.rb +13 -0
- data/lib/pakyow/support/configurable/config.rb +153 -0
- data/lib/pakyow/support/configurable/setting.rb +52 -0
- data/lib/pakyow/support/configurable.rb +103 -0
- data/lib/pakyow/support/core_refinements/array/ensurable.rb +25 -0
- data/lib/pakyow/support/core_refinements/method/introspection.rb +21 -0
- data/lib/pakyow/support/core_refinements/proc/introspection.rb +21 -0
- data/lib/pakyow/support/core_refinements/string/normalization.rb +50 -0
- data/lib/pakyow/support/deep_dup.rb +61 -0
- data/lib/pakyow/support/deep_freeze.rb +82 -0
- data/lib/pakyow/support/definable.rb +242 -0
- data/lib/pakyow/support/dependencies.rb +61 -0
- data/lib/pakyow/support/extension.rb +82 -0
- data/lib/pakyow/support/hookable.rb +227 -0
- data/lib/pakyow/support/indifferentize.rb +183 -0
- data/lib/pakyow/support/inflector.rb +13 -0
- data/lib/pakyow/support/inspectable.rb +88 -0
- data/lib/pakyow/support/logging.rb +31 -0
- data/lib/pakyow/support/makeable/object_maker.rb +30 -0
- data/lib/pakyow/support/makeable/object_name.rb +45 -0
- data/lib/pakyow/support/makeable/object_namespace.rb +28 -0
- data/lib/pakyow/support/makeable.rb +117 -0
- data/lib/pakyow/support/message_verifier.rb +74 -0
- data/lib/pakyow/support/path_version.rb +21 -0
- data/lib/pakyow/support/pipeline/object.rb +41 -0
- data/lib/pakyow/support/pipeline.rb +335 -0
- data/lib/pakyow/support/safe_string.rb +60 -0
- data/lib/pakyow/support/serializer.rb +49 -0
- data/lib/pakyow/support/silenceable.rb +21 -0
- data/lib/pakyow/support/string_builder.rb +62 -0
- data/lib/pakyow/support.rb +1 -0
- metadata +107 -26
- data/pakyow-support/LICENSE +0 -20
- data/pakyow-support/lib/pakyow/support/aargv.rb +0 -15
- data/pakyow-support/lib/pakyow/support/array.rb +0 -9
- data/pakyow-support/lib/pakyow/support/dir.rb +0 -32
- data/pakyow-support/lib/pakyow/support/dup.rb +0 -23
- data/pakyow-support/lib/pakyow/support/file.rb +0 -5
- data/pakyow-support/lib/pakyow/support/hash.rb +0 -47
- data/pakyow-support/lib/pakyow/support/kernel.rb +0 -9
- data/pakyow-support/lib/pakyow/support/string.rb +0 -36
- data/pakyow-support/lib/pakyow/support.rb +0 -8
- data/pakyow-support/lib/pakyow-support.rb +0 -1
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/class_state"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
# Makes it possible to define and call hooks on an object.
|
8
|
+
#
|
9
|
+
# Hooks can be defined at the class or instance level. When calling hooks
|
10
|
+
# on an instance, hooks defined on the class will be called first.
|
11
|
+
#
|
12
|
+
# By default, hooks are called in the order they are defined. Each hook
|
13
|
+
# can be assigned a relative priority to influence when it is to be called
|
14
|
+
# (relative to other hooks of the same type). Default hook priority is `0`,
|
15
|
+
# and can instead be set to `1` (high) or `-1` (low).
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# class Fish
|
19
|
+
# include Pakyow::Support::Hookable
|
20
|
+
# events :swim
|
21
|
+
#
|
22
|
+
# def swim
|
23
|
+
# performing "swim" do
|
24
|
+
# puts "swimming"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# Fish.before "swim" do
|
30
|
+
# puts "prepping"
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# fish = Fish.new
|
34
|
+
#
|
35
|
+
# fish.after "swim" do
|
36
|
+
# puts "resting"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# fish.swim
|
40
|
+
# => prepping
|
41
|
+
# swimming
|
42
|
+
# resting
|
43
|
+
#
|
44
|
+
module Hookable
|
45
|
+
# Known hook priorities.
|
46
|
+
#
|
47
|
+
PRIORITIES = { default: 0, high: 1, low: -1 }.freeze
|
48
|
+
|
49
|
+
def self.included(base)
|
50
|
+
base.include CommonMethods
|
51
|
+
base.include InstanceMethods
|
52
|
+
|
53
|
+
base.extend ClassMethods
|
54
|
+
|
55
|
+
base.extend ClassState
|
56
|
+
base.class_state :__events, default: [], inheritable: true, getter: false
|
57
|
+
base.class_state :__hooks, default: [], inheritable: true, getter: false
|
58
|
+
base.class_state :__hook_hash, default: { after: {}, before: {} }, inheritable: true
|
59
|
+
base.class_state :__hook_pipeline, default: { after: {}, before: {} }, inheritable: true
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
def known_event?(event)
|
64
|
+
self.class.known_event?(event.to_sym)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Class-level api methods.
|
68
|
+
#
|
69
|
+
module ClassMethods
|
70
|
+
attr_reader :__hook_pipeline
|
71
|
+
|
72
|
+
def self.extended(base)
|
73
|
+
base.extend(CommonMethods)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Sets the known events for the hookable object. Hooks registered for
|
77
|
+
# an event that doesn't exist will raise an ArgumentError.
|
78
|
+
#
|
79
|
+
# @param events [Array<Symbol>] The list of known events.
|
80
|
+
#
|
81
|
+
def events(*events)
|
82
|
+
@__events.concat(events.map(&:to_sym)).uniq!; @__events
|
83
|
+
end
|
84
|
+
|
85
|
+
# Defines a hook to call before event occurs.
|
86
|
+
#
|
87
|
+
# @param event [Symbol] The name of the event.
|
88
|
+
# @param priority [Symbol, Integer] The priority of the hook.
|
89
|
+
# Other priorities include:
|
90
|
+
# high (1)
|
91
|
+
# low (-1)
|
92
|
+
#
|
93
|
+
def before(event, name = nil, priority: PRIORITIES[:default], exec: true, &block)
|
94
|
+
add_hook(:before, event, name, priority, exec, block)
|
95
|
+
end
|
96
|
+
alias on before
|
97
|
+
|
98
|
+
# Defines a hook to call after event occurs.
|
99
|
+
#
|
100
|
+
# @see #before
|
101
|
+
#
|
102
|
+
def after(event, name = nil, priority: PRIORITIES[:default], exec: true, &block)
|
103
|
+
add_hook(:after, event, name, priority, exec, block)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Defines a hook to call before and after event occurs.
|
107
|
+
#
|
108
|
+
# @see #before
|
109
|
+
#
|
110
|
+
def around(event, name = nil, priority: PRIORITIES[:default], exec: true, &block)
|
111
|
+
add_hook(:before, event, name, priority, exec, block)
|
112
|
+
add_hook(:after, event, name, priority, exec, block)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @api private
|
116
|
+
def known_event?(event)
|
117
|
+
@__events.include?(event.to_sym)
|
118
|
+
end
|
119
|
+
|
120
|
+
def known_hook?(event)
|
121
|
+
@__hooks.any? { |hook|
|
122
|
+
hook[:name] == event.to_sym
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Methods included at the class and instance level.
|
128
|
+
#
|
129
|
+
module CommonMethods
|
130
|
+
# Calls all registered hooks for `event`, yielding between them.
|
131
|
+
#
|
132
|
+
# @param event [Symbol] The name of the event.
|
133
|
+
#
|
134
|
+
def performing(event, *args)
|
135
|
+
call_hooks(:before, event, *args)
|
136
|
+
value = yield
|
137
|
+
call_hooks(:after, event, *args)
|
138
|
+
value
|
139
|
+
end
|
140
|
+
|
141
|
+
# Calls all registered hooks of type, for event.
|
142
|
+
#
|
143
|
+
# @param type [Symbol] The type of event (e.g. before / after).
|
144
|
+
# @param event [Symbol] The name of the event.
|
145
|
+
#
|
146
|
+
def call_hooks(type, event, *args)
|
147
|
+
hooks(type, event).each do |hook|
|
148
|
+
if hook[:exec]
|
149
|
+
instance_exec(*args, &hook[:block])
|
150
|
+
else
|
151
|
+
hook[:block].call(*args)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# @api private
|
157
|
+
def hooks(type, event)
|
158
|
+
__hook_pipeline[type][event] || []
|
159
|
+
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
def add_hook(type, event, name, priority, exec, hook)
|
163
|
+
if priority.is_a?(Symbol)
|
164
|
+
priority = PRIORITIES[priority]
|
165
|
+
end
|
166
|
+
|
167
|
+
if known_event?(event) || known_hook?(event)
|
168
|
+
hook = {
|
169
|
+
type: type,
|
170
|
+
event: event.to_sym,
|
171
|
+
name: name ? name.to_sym : nil,
|
172
|
+
priority: priority,
|
173
|
+
block: hook,
|
174
|
+
exec: exec
|
175
|
+
}
|
176
|
+
|
177
|
+
(@__hook_hash[type.to_sym][event.to_sym] ||= []) << hook
|
178
|
+
@__hooks << hook
|
179
|
+
else
|
180
|
+
raise ArgumentError, "#{event} is not a known hook event"
|
181
|
+
end
|
182
|
+
|
183
|
+
reprioritize!(type, event)
|
184
|
+
pipeline!(type, event)
|
185
|
+
|
186
|
+
if known_hook?(event)
|
187
|
+
traverse_events_for_hook(event) do |hook_event|
|
188
|
+
pipeline!(:before, hook_event); pipeline!(:after, hook_event)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# @api private
|
194
|
+
def traverse_events_for_hook(name, &block)
|
195
|
+
if hook = @__hooks.find { |h| h[:name] == name.to_sym }
|
196
|
+
yield hook[:event]
|
197
|
+
traverse_events_for_hook(hook[:event], &block)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# @api private
|
202
|
+
def reprioritize!(type, event)
|
203
|
+
@__hook_hash[type.to_sym][event.to_sym] = @__hook_hash[type.to_sym][event.to_sym].group_by { |hook|
|
204
|
+
hook[:priority]
|
205
|
+
}.sort { |a, b|
|
206
|
+
b[0] <=> a[0]
|
207
|
+
}.flat_map { |group|
|
208
|
+
group[1]
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
# @api private
|
213
|
+
def pipeline!(type, event)
|
214
|
+
__hook_pipeline[type.to_sym][event.to_sym] = @__hook_hash.dig(type.to_sym, event.to_sym).to_a.flat_map { |hook|
|
215
|
+
[@__hook_pipeline[:before][hook[:name]].to_a, hook, @__hook_pipeline[:after][hook[:name]].to_a].flatten
|
216
|
+
}
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
module InstanceMethods
|
221
|
+
def __hook_pipeline
|
222
|
+
self.class.__hook_pipeline
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
# Creates a Hash-like object can access stored data with symbol or
|
8
|
+
# string keys.
|
9
|
+
#
|
10
|
+
# The original hash is converted to symbol keys, which means
|
11
|
+
# that a hash that originally contains a symbol and string key
|
12
|
+
# with the same symbold value will conflict. It is not guaranteed
|
13
|
+
# which value will be saved.
|
14
|
+
#
|
15
|
+
# IndifferentHash instances have the same api as Hash, but any method
|
16
|
+
# that would return a Hash, will return an IndifferentHash (with
|
17
|
+
# the exception of to_h/to_hash).
|
18
|
+
#
|
19
|
+
# NOTE: Please lookup Ruby's documentation for Hash to learn what
|
20
|
+
# methods are available.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# { test: "test1", "test" => "test2" } => { test: "test2" }
|
24
|
+
#
|
25
|
+
class IndifferentHash < SimpleDelegator
|
26
|
+
class << self
|
27
|
+
def deep(object)
|
28
|
+
hash = object.to_h
|
29
|
+
unless hash.empty?
|
30
|
+
hash = hash.each_with_object({}) { |(key, value), new_hash|
|
31
|
+
new_hash[key] = case value
|
32
|
+
when Hash
|
33
|
+
deep(value)
|
34
|
+
when Array
|
35
|
+
value.map { |value_item|
|
36
|
+
case value_item
|
37
|
+
when Hash
|
38
|
+
deep(value_item)
|
39
|
+
else
|
40
|
+
value_item
|
41
|
+
end
|
42
|
+
}
|
43
|
+
else
|
44
|
+
value
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
self.new(hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def indifferent_key_method(*methods)
|
55
|
+
methods.each do |name|
|
56
|
+
define_method(name) do |key = nil, *args, &block|
|
57
|
+
key = convert_key(key)
|
58
|
+
internal_hash.public_send(name, key, *args, &block)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def indifferent_multi_key_method(*methods)
|
64
|
+
methods.each do |name|
|
65
|
+
define_method(name) do |*keys, &block|
|
66
|
+
keys = keys.map { |key|
|
67
|
+
convert_key(key)
|
68
|
+
}
|
69
|
+
internal_hash.public_send(name, *keys, &block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def indifferentize_return_method(*methods)
|
75
|
+
methods.each do |name|
|
76
|
+
define_method(name) do |*args, &block|
|
77
|
+
hash = internal_hash.public_send(name, *args, &block)
|
78
|
+
self.class.new(hash) if hash
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def indifferentize_update_method(*methods)
|
84
|
+
methods.each do |name|
|
85
|
+
define_method(name) do |*args, &block|
|
86
|
+
args = args.map { |arg| stringify_keys(arg) }
|
87
|
+
hash = internal_hash.public_send(name, *args, &block)
|
88
|
+
self if hash
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def indifferentize_argument_method(*methods)
|
94
|
+
methods.each do |name|
|
95
|
+
define_method(name) do |*args, &block|
|
96
|
+
args = args.map { |arg| stringify_keys(arg) }
|
97
|
+
internal_hash.public_send(name, *args, &block)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def initialize(hash = {})
|
104
|
+
self.internal_hash = hash
|
105
|
+
end
|
106
|
+
|
107
|
+
indifferent_key_method :[], :[]=, :default, :delete, :fetch, :has_key?, :key?, :include?, :member?, :store
|
108
|
+
indifferent_multi_key_method :fetch_values, :values_at, :dig
|
109
|
+
indifferentize_return_method :merge, :invert, :compact, :reject, :select, :transform_values
|
110
|
+
indifferentize_update_method :merge!, :update, :replace, :clear, :keep_if, :delete_if, :compact!, :reject!, :select!
|
111
|
+
indifferentize_argument_method :>, :>=, :<=>, :<, :<=, :==
|
112
|
+
|
113
|
+
def internal_hash
|
114
|
+
__getobj__
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_h
|
118
|
+
internal_hash.each_with_object({}) { |(key, value), new_hash|
|
119
|
+
key = case key
|
120
|
+
when String
|
121
|
+
key.to_sym
|
122
|
+
else
|
123
|
+
key
|
124
|
+
end
|
125
|
+
|
126
|
+
value = case value
|
127
|
+
when IndifferentHash
|
128
|
+
value.to_h
|
129
|
+
else
|
130
|
+
value
|
131
|
+
end
|
132
|
+
|
133
|
+
new_hash[key] = value
|
134
|
+
}
|
135
|
+
end
|
136
|
+
alias to_hash to_h
|
137
|
+
|
138
|
+
# Fixes an issue using pp inside a delegator.
|
139
|
+
#
|
140
|
+
def pp(*args)
|
141
|
+
Kernel.pp(*args)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def internal_hash=(other)
|
147
|
+
__setobj__(stringify_keys(other))
|
148
|
+
end
|
149
|
+
|
150
|
+
def stringify_keys(object)
|
151
|
+
return object unless object.respond_to?(:to_h)
|
152
|
+
|
153
|
+
converted = {}
|
154
|
+
object.to_h.each do |key, value|
|
155
|
+
converted[convert_key(key)] = value
|
156
|
+
end
|
157
|
+
|
158
|
+
converted
|
159
|
+
end
|
160
|
+
|
161
|
+
def convert_key(key)
|
162
|
+
case key
|
163
|
+
when Symbol
|
164
|
+
key.to_s
|
165
|
+
else
|
166
|
+
key
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
module Indifferentize
|
172
|
+
refine Hash do
|
173
|
+
def indifferentize
|
174
|
+
Pakyow::Support::IndifferentHash.new(self)
|
175
|
+
end
|
176
|
+
|
177
|
+
def deep_indifferentize
|
178
|
+
Pakyow::Support::IndifferentHash.deep(self)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/class_state"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
# Customized inspectors for your objects.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class FooBar
|
11
|
+
# include Pakyow::Support::Inspectable
|
12
|
+
# inspectable :@foo, :baz
|
13
|
+
#
|
14
|
+
# def initialize
|
15
|
+
# @foo = :foo
|
16
|
+
# @bar = :bar
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def baz
|
20
|
+
# :baz
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# FooBar.instance.inspect
|
25
|
+
# => #<FooBar:0x007fd3330248c0 @foo=:foo baz=:baz>
|
26
|
+
#
|
27
|
+
module Inspectable
|
28
|
+
def self.included(base)
|
29
|
+
base.extend ClassMethods
|
30
|
+
base.extend ClassState unless base.ancestors.include?(ClassState)
|
31
|
+
base.class_state :__inspectables, inheritable: true, default: []
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
# Sets the instance vars and public methods that should be part of the inspection.
|
36
|
+
#
|
37
|
+
# @param inspectables [Array<Symbol>] The list of instance variables and public methods.
|
38
|
+
#
|
39
|
+
def inspectable(*inspectables)
|
40
|
+
@__inspectables = inspectables.map(&:to_sym)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Recursion protection based on:
|
45
|
+
# https://stackoverflow.com/a/5772445
|
46
|
+
#
|
47
|
+
def inspect
|
48
|
+
inspection = String.new("#<#{self.class}:#{self.object_id}")
|
49
|
+
|
50
|
+
if recursive_inspect?
|
51
|
+
"#{inspection} ...>"
|
52
|
+
else
|
53
|
+
prevent_inspect_recursion do
|
54
|
+
if self.class.__inspectables.any?
|
55
|
+
inspection << " " + self.class.__inspectables.map { |inspectable|
|
56
|
+
value = if inspectable.to_s.start_with?("@")
|
57
|
+
instance_variable_get(inspectable)
|
58
|
+
else
|
59
|
+
send(inspectable)
|
60
|
+
end
|
61
|
+
|
62
|
+
"#{inspectable}=#{value.inspect}"
|
63
|
+
}.join(", ")
|
64
|
+
end
|
65
|
+
|
66
|
+
inspection.strip << ">"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def inspected_objects
|
74
|
+
Thread.current[:inspected_objects] ||= {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def prevent_inspect_recursion
|
78
|
+
inspected_objects[object_id] = true; yield
|
79
|
+
ensure
|
80
|
+
inspected_objects.delete(object_id)
|
81
|
+
end
|
82
|
+
|
83
|
+
def recursive_inspect?
|
84
|
+
inspected_objects[object_id]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
module Logging
|
8
|
+
# Yields Pakyow.logger if defined, otherwise raises `error`.
|
9
|
+
#
|
10
|
+
def self.yield_or_raise(error)
|
11
|
+
if defined?(Pakyow.logger)
|
12
|
+
yield(Pakyow.logger)
|
13
|
+
else
|
14
|
+
raise error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Yields Pakyow.logger if defined, or a default logger.
|
19
|
+
#
|
20
|
+
def self.safe
|
21
|
+
logger = if defined?(Pakyow.logger) && Pakyow.logger
|
22
|
+
Pakyow.logger
|
23
|
+
else
|
24
|
+
::Logger.new($stdout)
|
25
|
+
end
|
26
|
+
|
27
|
+
yield logger
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/inflector"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
# @api private
|
8
|
+
module ObjectMaker
|
9
|
+
def self.define_const_for_object_with_name(object_to_define, object_name)
|
10
|
+
return if object_name.nil?
|
11
|
+
|
12
|
+
target = object_name.namespace.parts.inject(Object) { |target_for_part, object_name_part|
|
13
|
+
ObjectMaker.define_object_on_target_with_constant_name(Module.new, target_for_part, object_name_part)
|
14
|
+
}
|
15
|
+
|
16
|
+
ObjectMaker.define_object_on_target_with_constant_name(object_to_define, target, object_name.name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.define_object_on_target_with_constant_name(object, target, constant_name)
|
20
|
+
constant_name = Support.inflector.camelize(constant_name)
|
21
|
+
|
22
|
+
unless target.const_defined?(constant_name, false)
|
23
|
+
target.const_set(constant_name, object)
|
24
|
+
end
|
25
|
+
|
26
|
+
target.const_get(constant_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/inflector"
|
4
|
+
require "pakyow/support/makeable/object_namespace"
|
5
|
+
|
6
|
+
module Pakyow
|
7
|
+
module Support
|
8
|
+
# @api private
|
9
|
+
class ObjectName
|
10
|
+
class << self
|
11
|
+
def namespace(*namespaces, object_name)
|
12
|
+
ObjectName.new(
|
13
|
+
ObjectNamespace.new(*namespaces),
|
14
|
+
object_name
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :namespace, :name
|
20
|
+
|
21
|
+
def initialize(namespace, name)
|
22
|
+
@namespace, @name = namespace, name.to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
def isolated(subobject_name)
|
26
|
+
ObjectName.new(
|
27
|
+
ObjectNamespace.new(*parts),
|
28
|
+
subobject_name
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def parts
|
33
|
+
namespace.parts + [@name]
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
[@namespace, @name].join("/")
|
38
|
+
end
|
39
|
+
|
40
|
+
def constant
|
41
|
+
[@namespace.constant, Support.inflector.camelize(@name)].join("::")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/inflector"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Support
|
7
|
+
# @api private
|
8
|
+
class ObjectNamespace
|
9
|
+
def initialize(*namespaces)
|
10
|
+
@namespaces = namespaces.map(&:to_sym)
|
11
|
+
end
|
12
|
+
|
13
|
+
def parts
|
14
|
+
@namespaces
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@namespaces.join("/")
|
19
|
+
end
|
20
|
+
|
21
|
+
def constant
|
22
|
+
@namespaces.map { |namespace|
|
23
|
+
Support.inflector.camelize(namespace)
|
24
|
+
}.join("::")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|