eco-helpers 3.0.27 → 3.0.29
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 +52 -1
- data/eco-helpers.gemspec +1 -0
- data/lib/eco/api/common/class_helpers.rb +1 -136
- data/lib/eco/api/common/loaders/config/cli.rb +1 -1
- data/lib/eco/api/common/loaders/config/session.rb +1 -1
- data/lib/eco/api/common/loaders/config/workflow.rb +1 -1
- data/lib/eco/api/common/loaders/config.rb +2 -5
- data/lib/eco/api/common/loaders/use_case/target_model.rb +1 -1
- data/lib/eco/api/common/loaders/use_case/type.rb +1 -1
- data/lib/eco/api/common/people/supervisor_helpers.rb +3 -1
- data/lib/eco/api/common/session/helpers/prompt_user.rb +3 -1
- data/lib/eco/api/common/session/logger/channels.rb +1 -0
- data/lib/eco/api/common/session/sftp.rb +9 -2
- data/lib/eco/api/session/batch/job/sets.rb +1 -0
- data/lib/eco/api/session/batch/job/type.rb +1 -0
- data/lib/eco/api/session/batch/launcher/valid_methods.rb +3 -2
- data/lib/eco/api/usecases/base_case/model.rb +2 -1
- data/lib/eco/api/usecases/base_case/type.rb +2 -1
- data/lib/eco/api/usecases/base_io/validations.rb +2 -1
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/commandable.rb +3 -2
- data/lib/eco/api/usecases/lib/files/file_pattern.rb +0 -2
- data/lib/eco/api/usecases/lib/files/sftp.rb +9 -6
- data/lib/eco/api/usecases/samples/drivers/sftp_sample.rb +3 -1
- data/lib/eco/api/usecases/service/sftp.rb +36 -0
- data/lib/eco/api/usecases/service.rb +15 -0
- data/lib/eco/api/usecases.rb +1 -0
- data/lib/eco/data/files/helpers.rb +4 -2
- data/lib/eco/data/fuzzy_match.rb +4 -2
- data/lib/eco/data/hashes/diff_result/meta.rb +2 -1
- data/lib/eco/data/locations/node_diff/accessors.rb +2 -1
- data/lib/eco/language/delegation/chainable_delegator.rb +18 -0
- data/lib/eco/language/delegation/delegating_blank.rb +162 -0
- data/lib/eco/language/delegation/delegating_missing.rb +104 -0
- data/lib/eco/language/delegation/delegating_missing_const.rb +53 -0
- data/lib/eco/language/delegation/delegating_missing_on_class.rb +53 -0
- data/lib/eco/language/delegation/{const_delegator.rb → for_delegator/const_delegator.rb} +8 -6
- data/lib/eco/language/delegation/{const_lookup_hooks.rb → for_delegator/const_lookup_hooks.rb} +37 -19
- data/lib/eco/language/delegation/{delegated_class.rb → for_delegator/delegated_class.rb} +6 -19
- data/lib/eco/language/delegation/for_delegator.rb +11 -0
- data/lib/eco/language/delegation.rb +6 -3
- data/lib/eco/language/klass/builder.rb +29 -0
- data/lib/eco/language/klass/helpers_built.rb +9 -0
- data/lib/eco/language/klass/hierarchy.rb +34 -0
- data/lib/eco/language/klass/inheritable_class_vars.rb +45 -0
- data/lib/eco/language/klass/naming.rb +21 -0
- data/lib/eco/language/klass/resolver.rb +30 -0
- data/lib/eco/language/klass/when_inherited.rb +10 -13
- data/lib/eco/language/klass.rb +6 -0
- data/lib/eco/language/methods.rb +0 -1
- data/lib/eco/language/strings/underscore.rb +17 -0
- data/lib/eco/language/strings.rb +8 -0
- data/lib/eco/language.rb +1 -0
- data/lib/eco/version.rb +1 -1
- metadata +35 -6
- data/lib/eco/language/methods/delegate_missing.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48e3cb15eee9eccde5ed9781dbff0ebcf811d26b1a7f23f503e3de733b60c19b
|
4
|
+
data.tar.gz: b4a84a5c1b4496706292044964256d80728f7dadabc975937306fa2f08ae29d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd7335d81867d2d954a692e071ed3ca42b9c1510d8ef166a3eff0ec317e9254d4bf42a319dadb0a894c8689808ac55769dcdb6687124457e575c38c134fc70ba
|
7
|
+
data.tar.gz: 4364f5451f67f91228e27ad40daf10af8c2db1b99d907be9cdb84b983bb5e9f274dfddc13be174a1bed2ca4dd7c8ee42b4ffec23eaeba3ae05bae761ed5fe223
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,58 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
|
5
|
-
## [3.0.
|
5
|
+
## [3.0.30] - 2025-03-xx
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
## [3.0.29] - 2025-03-31
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- `API::UseCases::Service::Sftp` **basic wrapper** to make this easier on Sftp functions.
|
18
|
+
- `Language::Delegation::DelegatingBlank`
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
|
22
|
+
- `Eco::API::UseCases::Lib::Files::Sftp`
|
23
|
+
- **Rectified** named argument `only_latest` to fetch only latest file (**newest**).
|
24
|
+
- Wrong target object to call `#upload` on.
|
25
|
+
|
26
|
+
## [3.0.28] - 2025-03-31
|
27
|
+
|
28
|
+
### Added
|
29
|
+
|
30
|
+
- `Language::Delegation::DelegatingMissing` (rails alike, but ending with `ing`).
|
31
|
+
- `Language::Delegation::DelegatingMissingConst`.
|
32
|
+
- `Language::Delegation::ChainableDelegator`
|
33
|
+
- `Language::Strings::Underscore`
|
34
|
+
- `Eco::API::UseCases::Lib::Files::Sftp`
|
35
|
+
- **Added** named argument `only_latest` to fetch only latest file (**newest**).
|
36
|
+
|
37
|
+
### Changed
|
38
|
+
|
39
|
+
- `Eco::API::UseCases::Lib::Files::Sftp#local_folder`
|
40
|
+
- **Remove** default to `.` (current/root directory).
|
41
|
+
- **Moved** `Language::Methods::DelegateMissing` to `Language::Delegation::DelegatingMissingOnClass`
|
42
|
+
- **Renamed** `::delegate_missing_to` to `::delegating_missing_on_class_to`
|
43
|
+
- **Moved** `DelegatedClass`, `ConstDelegator` and `ConstLookupHooks` from `Language::Delegation` to `Language::Delegation::ForDelegator`
|
44
|
+
- `DelegatedClass`
|
45
|
+
- **Moved** `#initialize` to the **new** `ChainableDelegator` sample
|
46
|
+
- **Moved** requirement for base to be a `Delegator` or subclass thereof.
|
47
|
+
- The requirement is now part of `ConstLookupHooks`, as this particular concern only makes sense on `Delegator` subclasses.
|
48
|
+
- **Moved** (by keeping backwards compatibility) `Eco::API::Common::ClassHelpers` to decoupled helpers in `Eco::Language::Klass`
|
49
|
+
- **Manage Exception** on `Eco::API::Common::Session::SFTP#upload`
|
50
|
+
- **Added** remote `dest_file` feedback
|
51
|
+
|
52
|
+
### Fixed
|
53
|
+
|
54
|
+
- **Remove** recursive call on `Lib::Files::FilePattern#file_pattern_const`
|
55
|
+
|
56
|
+
## [3.0.27] - 2025-03-29
|
6
57
|
|
7
58
|
### Added
|
8
59
|
|
data/eco-helpers.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
#spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
+
spec.add_development_dependency 'byebug'
|
30
31
|
spec.add_development_dependency 'rake', '>= 13.0.3', '< 14'
|
31
32
|
spec.add_development_dependency 'redcarpet', '>= 3.6.0', '< 4'
|
32
33
|
spec.add_development_dependency 'rspec', '>= 3.12.0', '< 4'
|
@@ -2,142 +2,7 @@ module Eco
|
|
2
2
|
module API
|
3
3
|
module Common
|
4
4
|
module ClassHelpers
|
5
|
-
|
6
|
-
def class_resolver(name, klass)
|
7
|
-
define_singleton_method(name) { resolve_class(klass) }
|
8
|
-
define_method(name) { self.class.resolve_class(klass) }
|
9
|
-
end
|
10
|
-
|
11
|
-
# With given a `klass` name it resolves to an actual `Class`
|
12
|
-
# @return [Class] the class that was being searched by name `klass`.
|
13
|
-
def resolve_class(klass, exception: true)
|
14
|
-
@resolved ||= {}
|
15
|
-
@resolved[klass] ||=
|
16
|
-
case klass
|
17
|
-
when Class
|
18
|
-
klass
|
19
|
-
when String
|
20
|
-
begin
|
21
|
-
Kernel.const_get(klass)
|
22
|
-
rescue NameError
|
23
|
-
raise if exception
|
24
|
-
end
|
25
|
-
when Symbol
|
26
|
-
resolve_class(send(klass))
|
27
|
-
else
|
28
|
-
raise "Unknown class: #{klass}" if exception
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Helper to normalize `key` into a correct `ruby` **constant name**
|
33
|
-
# @param key [String, Symbol] to be normalized
|
34
|
-
# @return [String] a correct constant name
|
35
|
-
def to_constant(key)
|
36
|
-
key.to_s.strip.split(/[\-\_ ]/i).compact.map do |str|
|
37
|
-
str.slice(0).upcase + str.slice(1..-1).downcase
|
38
|
-
end.join
|
39
|
-
end
|
40
|
-
|
41
|
-
# Helper to create an instance variable `name`
|
42
|
-
# @param [String, Symbol] the name of the variable
|
43
|
-
# @reutrn [String] the name of the created instance variable
|
44
|
-
def instance_variable_name(name)
|
45
|
-
str = name.to_s
|
46
|
-
str = "@#{str}" unless str.start_with?("@")
|
47
|
-
str
|
48
|
-
end
|
49
|
-
|
50
|
-
# If the class for `name` exists, it returns it. Otherwise it generates it.
|
51
|
-
# @param name [String, Symbol] the name of the new class
|
52
|
-
# @param inherits [Class] the parent class to _inherit_ from
|
53
|
-
# @param parent_space [String] parent namespace of the generated class, if not given: `self`
|
54
|
-
# @yield [child_class] configure the new class
|
55
|
-
# @yieldparam child_class [Class] the new class
|
56
|
-
# @return [Class] the new generated class
|
57
|
-
def new_class(name, inherits:, parent_space: nil)
|
58
|
-
name = name.to_sym.freeze
|
59
|
-
class_name = to_constant(name)
|
60
|
-
parent_space = parent_space ? resolve_class(parent_space) : self
|
61
|
-
full_class_name = "#{parent_space}::#{class_name}"
|
62
|
-
|
63
|
-
unless (target_class = resolve_class(full_class_name, exception: false))
|
64
|
-
target_class = Class.new(inherits)
|
65
|
-
parent_space.const_set class_name, target_class
|
66
|
-
end
|
67
|
-
|
68
|
-
target_class.tap do |klass|
|
69
|
-
yield(klass) if block_given?
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Finds all child classes of the current class.
|
74
|
-
# @param parent_class [Class] the parent class we want to find children of.
|
75
|
-
# @param direct [Boolean] it will only include direct child classes.
|
76
|
-
# @param scope [nil, Array] to only look for descendants among the ones in `scope`.
|
77
|
-
# @return [Arrary<Class>] the child classes in hierarchy order.
|
78
|
-
def descendants(parent_class: self, direct: false, scope: nil)
|
79
|
-
scope ||= ObjectSpace.each_object(::Class)
|
80
|
-
return [] if scope.empty?
|
81
|
-
scope.select do |klass|
|
82
|
-
klass < parent_class
|
83
|
-
end.sort do |k_1, k_2|
|
84
|
-
next -1 if k_2 < k_1
|
85
|
-
next 1 if k_1 < k_2
|
86
|
-
0
|
87
|
-
end.tap do |siblings|
|
88
|
-
if direct
|
89
|
-
siblings.reject! do |si|
|
90
|
-
siblings.any? {|s| si < s}
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# @param parent_class [Class] the parent class we want to find children of.
|
97
|
-
# @param direct [Boolean] it will only include direct child classes.
|
98
|
-
# @return [Boolean] `true` if the current class has child classes, and `false` otherwise.
|
99
|
-
def descendants?(parent_class: self, direct: false)
|
100
|
-
descendants(parent_class: parent_class, direct: direct).length.positive?
|
101
|
-
end
|
102
|
-
|
103
|
-
# Keeps track on class instance variables that should be inherited by child classes.
|
104
|
-
# @note
|
105
|
-
# - subclasses will inherit the value as is at that moment
|
106
|
-
# - any change afterwards will be only on the specific class (in line with class instance variables)
|
107
|
-
# - adapted from https://stackoverflow.com/a/10729812/4352306
|
108
|
-
# TODO: this separates the logic of the method to the instance var.
|
109
|
-
# Think if would be possible to join them somehow.
|
110
|
-
def inheritable_class_vars(*vars)
|
111
|
-
@inheritable_class_vars ||= [:inheritable_class_vars]
|
112
|
-
@inheritable_class_vars += vars
|
113
|
-
end
|
114
|
-
|
115
|
-
# Builds the attr_reader and attr_writer of `attrs` and registers
|
116
|
-
# the associated instance variable as inheritable.
|
117
|
-
def inheritable_attrs(*attrs)
|
118
|
-
attrs.each do |attr|
|
119
|
-
class_eval %(
|
120
|
-
class << self; attr_accessor :#{attr} end
|
121
|
-
), __FILE__, __LINE__ - 2
|
122
|
-
end
|
123
|
-
|
124
|
-
inheritable_class_vars(*attrs)
|
125
|
-
end
|
126
|
-
|
127
|
-
# This callback method is called whenever a subclass of the current class is created.
|
128
|
-
# @note
|
129
|
-
# - values of the instance variables are copied as they are (no dups or clones)
|
130
|
-
# - the above means: avoid methods that change the state of the mutable object on it
|
131
|
-
# - mutating methods would reflect the changes on other classes as well
|
132
|
-
# - therefore, `freeze` will be called on the values that are inherited.
|
133
|
-
def inherited(subclass)
|
134
|
-
super
|
135
|
-
inheritable_class_vars.each do |var|
|
136
|
-
instance_var = instance_variable_name(var)
|
137
|
-
value = instance_variable_get(instance_var)
|
138
|
-
subclass.instance_variable_set(instance_var, value.freeze)
|
139
|
-
end
|
140
|
-
end
|
5
|
+
include Eco::Language::Klass::HelpersBuilt
|
141
6
|
end
|
142
7
|
end
|
143
8
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
class Eco::API::Common::Loaders::Config
|
2
|
-
|
3
|
-
extend Eco::Language::Methods::DelegateMissing
|
2
|
+
include Eco::Language::Delegation::DelegatingMissingOnClass
|
4
3
|
|
5
|
-
|
4
|
+
delegating_missing_on_class_to :config
|
6
5
|
|
7
6
|
class << self
|
8
7
|
# To create samples of configurations
|
@@ -29,8 +28,6 @@ class Eco::API::Common::Loaders::Config
|
|
29
28
|
config.active_enviro
|
30
29
|
end
|
31
30
|
end
|
32
|
-
|
33
|
-
delegate_missing_to :config
|
34
31
|
end
|
35
32
|
|
36
33
|
require_relative 'config/cli'
|
@@ -5,7 +5,7 @@ module Eco
|
|
5
5
|
module Helpers
|
6
6
|
module PromptUser
|
7
7
|
# Prompts user for input with option for default on timeout.
|
8
|
-
def prompt_user(question, default:, explanation:
|
8
|
+
def prompt_user(question, default:, explanation: '', timeout: nil)
|
9
9
|
require 'timeout'
|
10
10
|
response =
|
11
11
|
if config.run_mode_remote?
|
@@ -18,6 +18,8 @@ module Eco
|
|
18
18
|
begin
|
19
19
|
Timeout::timeout(timeout) { STDIN.gets.chop }
|
20
20
|
rescue Timeout::Error
|
21
|
+
print default
|
22
|
+
puts "\n"
|
21
23
|
default
|
22
24
|
end
|
23
25
|
else
|
@@ -118,6 +118,7 @@ module Eco
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# Upload a file to the specific `remote_folder`
|
121
|
+
# @return [String, FalseClass] on success returns the remote file path.
|
121
122
|
def upload(local_file, remote_folder:, gid: nil)
|
122
123
|
return false unless local_file && File.exist?(local_file)
|
123
124
|
|
@@ -133,9 +134,15 @@ module Eco
|
|
133
134
|
end
|
134
135
|
|
135
136
|
log(:info) {
|
136
|
-
"Uploaded '#{local_file}' (#{res})"
|
137
|
+
"Uploaded '#{local_file}' as '#{dest_file}' (#{res})"
|
137
138
|
}
|
138
|
-
|
139
|
+
|
140
|
+
dest_file
|
141
|
+
rescue StandardError
|
142
|
+
log(:error) {
|
143
|
+
"Could not upload file '#{dest_file}' (#{res})"
|
144
|
+
}
|
145
|
+
raise
|
139
146
|
end
|
140
147
|
|
141
148
|
private
|
@@ -8,8 +8,9 @@ module Eco::API::UseCases::Lib::Files
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
+
# @return [String, FalseClass] the path of the remote file or `false` if failed.
|
11
12
|
def upload(local_file, subfolder: remote_subfolder, gid: sftp_group_id)
|
12
|
-
|
13
|
+
sftp.upload(
|
13
14
|
local_file,
|
14
15
|
remote_folder: remote_folder(subfolder),
|
15
16
|
gid: gid
|
@@ -34,15 +35,19 @@ module Eco::API::UseCases::Lib::Files
|
|
34
35
|
subfolder: remote_subfolder,
|
35
36
|
pattern: nil,
|
36
37
|
local_folder: self.local_folder,
|
38
|
+
only_latest: false,
|
37
39
|
&block
|
38
40
|
)
|
39
41
|
remote_files = with_remote_files(subfolder: subfolder, pattern: pattern)
|
40
|
-
|
42
|
+
|
43
|
+
return [] if remote_files.empty?
|
44
|
+
remote_files = [remote_files.last] if only_latest
|
41
45
|
|
42
46
|
file_names = remote_files.map {|file| to_remote_path(file.name, subfolder: subfolder)}
|
43
47
|
|
44
48
|
log(:info) {
|
45
|
-
msg = "Getting the following files into the local folder
|
49
|
+
msg = "Getting the following files into the local folder "
|
50
|
+
msg << "'#{local_folder || '.'}':\n"
|
46
51
|
msg << ' * '
|
47
52
|
msg << file_names.join("\n * ")
|
48
53
|
msg
|
@@ -87,7 +92,7 @@ module Eco::API::UseCases::Lib::Files
|
|
87
92
|
files = with_remote_files(subfolder: subfolder, pattern: pattern)
|
88
93
|
return if files.empty?
|
89
94
|
|
90
|
-
msg = "There are
|
95
|
+
msg = "There are files in the remote folder that will be deleted: '#{subfolder}':\n"
|
91
96
|
msg << ' * '
|
92
97
|
str = files.map(&:longname).join("\n * ")
|
93
98
|
str << "\n"
|
@@ -118,8 +123,6 @@ module Eco::API::UseCases::Lib::Files
|
|
118
123
|
local_dir
|
119
124
|
elsif self.class.const_defined?(:LOCAL_FOLDER)
|
120
125
|
self.class::LOCAL_FOLDER
|
121
|
-
else
|
122
|
-
'.'
|
123
126
|
end
|
124
127
|
end
|
125
128
|
|
@@ -37,7 +37,9 @@ class Eco::API::UseCases::Samples::Drivers::Sftp < Eco::API::Common::Loaders::Us
|
|
37
37
|
|
38
38
|
file_names = files.map {|file| to_remote_path(file.name)}
|
39
39
|
|
40
|
-
|
40
|
+
msg = "Getting the following files into the local folder "
|
41
|
+
msg << "'#{local_folder || '.'}':"
|
42
|
+
puts msg
|
41
43
|
puts file_names
|
42
44
|
|
43
45
|
sftp.download(file_names, local_folder: local_folder)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Eco::API::UseCases::Service
|
2
|
+
# Class that pulls configuration from the subject (i.e. `remote_folder`)
|
3
|
+
class Sftp
|
4
|
+
include Eco::API::UseCases::Lib::Files::Sftp
|
5
|
+
# include Eco::Language::Delegation::DelegatingMissing
|
6
|
+
include Eco::Language::Delegation::DelegatingMissingConst
|
7
|
+
include Eco::Language::Delegation::DelegatingBlank
|
8
|
+
|
9
|
+
DELEGATED_BLANK_PROPERTIES = %i[
|
10
|
+
remote_subfolder
|
11
|
+
local_folder
|
12
|
+
sftp_group_id
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
delegating_missing_to :subject
|
16
|
+
delegating_blank(*DELEGATED_BLANK_PROPERTIES, to: :subject, safe: true)
|
17
|
+
|
18
|
+
def initialize(subject)
|
19
|
+
@subject = subject
|
20
|
+
end
|
21
|
+
|
22
|
+
# @note overriding Sftp `attr_reader`
|
23
|
+
def session
|
24
|
+
subject.send(:session)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @note overriding Sftp `attr_reader`
|
28
|
+
def options
|
29
|
+
subject.send(:options)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :subject
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
class UseCases
|
4
|
+
# Service classes tied to `UseCases`
|
5
|
+
# @note its purpose to keep `UseCase` classes as dry as possible.
|
6
|
+
# Rather than including methods into the use case, a service class
|
7
|
+
# approach can prevent undesirable clashes, that in turn are very
|
8
|
+
# difficult to track down.
|
9
|
+
module Service
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require_relative 'service/sftp'
|
data/lib/eco/api/usecases.rb
CHANGED
@@ -177,6 +177,7 @@ require_relative 'usecases/base_io'
|
|
177
177
|
require_relative 'usecases/use_case_io'
|
178
178
|
require_relative 'usecases/cli'
|
179
179
|
require_relative 'usecases/lib'
|
180
|
+
require_relative 'usecases/service'
|
180
181
|
require_relative 'usecases/graphql'
|
181
182
|
require_relative 'usecases/default'
|
182
183
|
require_relative 'usecases/samples'
|
data/lib/eco/data/fuzzy_match.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Eco::Language::Delegation
|
2
|
+
class ChainableDelegator < SimpleDelegator
|
3
|
+
include ForDelegator::DelegatedClass
|
4
|
+
include ForDelegator::ConstDelegator
|
5
|
+
include ForDelegator::ConstLookupHooks
|
6
|
+
|
7
|
+
# It allows to chain delegators, when the first parameter is an
|
8
|
+
# instance of `delegated_class`.
|
9
|
+
# @note it also allows to create an instance of `delegated_class`
|
10
|
+
# on initialization.
|
11
|
+
def initialize(*args, **kargs, &block)
|
12
|
+
obj = args.first
|
13
|
+
obj = new(*args, **kargs, &block) unless of_kind?(obj)
|
14
|
+
|
15
|
+
super(obj)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|