as_method 0.1.1 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8c21ee102f42fb035e7548aa149656c9ce4dac89a7801ad20d4a3f8211d45a9
4
- data.tar.gz: e50f9a3f26f0e44b9ba912703c78d47d8ca6540be1345ad6f63ab8e3b3933299
3
+ metadata.gz: 2d9af230121d5102e4fe40bad36aa60286115dd5ffc13fb69c2f7228d3d27d7a
4
+ data.tar.gz: 53d7e4db5c3ea9c77d767794fbee5466f205aa4038e2e25753a605dc40ae6813
5
5
  SHA512:
6
- metadata.gz: db3c2fb9ed080a528aa9b6adae0c55f52c862e74e9993776f42d6e30adce5f8248f5973539938bd8bafb3ed325e6b2d16ca54c595f14be60632507cfddd44a22
7
- data.tar.gz: ec21c57976ba5024d23d6c4650f5330dce9a0b0a9bac65210510ba6983ce8edc1e895d847c7e54872a3c2ca247fcb465c0992dbe0c920a920843dcf988f22d2d
6
+ metadata.gz: 0b76457eed2af6cc5ef73eaa254d3beb927bfe06bd3a1fed6b4eb9ddc6e01e3767ec3585b13e14885594bd11b61f2ec0ab3aec8cf1b562f278a0c2092b877b88
7
+ data.tar.gz: e8dd515b04ee6afd28b7b18ff8e2f0a32f0f0ef7f64636517c9b99f40ae66b25780a81118eab4c0dbd8c54a4ba1fad950a7421503799d58f9b494d254509a33c
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
- # Includable Service Objects
1
+ # Service Object Injection
2
+
3
+ Static dependency injection at its best.
2
4
 
3
5
  Usage example:
4
6
 
5
7
  ```ruby
6
8
  class CreateUser
7
- include as_method ValidateUserAttributes, name: :validate!
8
- include as_method Generators::GeneratePassword
9
- include as_method SaveModel, name: :save
9
+ include as_method ValidateUserEntity, name: :validate!
10
+ include as_method Generators::GeneratePassword # -> generate_password()
11
+ include as_method SaveEntity, name: :save
10
12
 
11
13
  def call(name, email)
12
14
  @name = name
@@ -16,6 +18,8 @@ class CreateUser
16
18
  save(user)
17
19
  end
18
20
 
21
+ def self.call(...) = new.call(...)
22
+
19
23
  private
20
24
 
21
25
  def attributes
@@ -31,24 +35,59 @@ end
31
35
  ## Why?
32
36
 
33
37
  This approach allows you to:
34
- - keep bringing reusable methods in the old-fashioned way via `include`, just like our ancestors did;
35
- - make methods extracted to SOs look and feel just like regular methods;
36
- - have all used Service Objects (SOs) listed as explicit dependencies;
38
+ - keep bringing reusable methods in the old-fashioned way via `include` or `extend`, just like our ancestors did;
39
+ - make Service Objects (SOs) look and feel just like regular methods;
40
+ - have all used SOs listed as explicit dependencies in-place;
41
+
42
+ ## YouTube video about the Gem
43
+
44
+ Click on the image below:
45
+
46
+ <div align="left">
47
+ <a href="https://www.youtube.com/watch?v=eX7DLJJUEI8">
48
+ <img src="https://img.youtube.com/vi/eX7DLJJUEI8/0.jpg" style="width:100%;">
49
+ </a>
50
+ </div>
37
51
 
38
52
  ## Compatibility
39
53
 
40
- Tested on Ruby v2.4 .. v3.1, but it is expected to work on all 2.x versions.
54
+ Tested on Ruby v2.4 .. v3.x, but it is expected to work on all 2.x versions.
41
55
 
42
56
  ## Installation
43
57
 
58
+ > [!IMPORTANT]
59
+ > Due to a temporary issue the RubyGems currently installs an outdated version of the gem.
60
+ >
61
+ > **For the Latest Version:** To access the most recent version of the gem, please clone it directly from this GitHub repository.
62
+
63
+
44
64
  Add to your `Gemfile`
45
65
 
46
66
  ```ruby
47
67
  gem "as_method"
48
68
  ```
49
69
 
50
- To make `as_method` class method available in all classes, add this line to your application loader:
70
+ To make `as_method` class method available in _all classes and modules_, add this line to your application loader:
51
71
 
52
72
  ```ruby
53
73
  require "as_method/setup"
54
74
  ```
75
+
76
+ or enable it in place:
77
+
78
+ ```ruby
79
+ class MyClass
80
+ extend AsMethod::Allow
81
+ ...
82
+ end
83
+ ```
84
+
85
+ ## Alternatives
86
+
87
+ If you require dependency injection _during object construction_, you might consider using [dry-auto_inject](https://dry-rb.org/gems/dry-auto_inject).
88
+
89
+ However, be aware of the following points:
90
+
91
+ - Dependencies are somewhat implicit as they are defined in a separate file.
92
+ - Object constructors get modified, as explained in detail [here](https://dry-rb.org/gems/dry-auto_inject/0.6/how-does-it-work/)."
93
+ - Resulting methods don't invoke 'call' on objects, they return callables instead.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AsMethod
4
+ module Allow
5
+
6
+ def self.included(_)
7
+ raise "Don't include, extend instead"
8
+ end
9
+
10
+ def self.extended(base)
11
+ if base.is_a?(Class)
12
+ base.extend(Helpers::ClassMethods)
13
+ base.include(Helpers::InstanceMethods)
14
+ else
15
+ base.singleton_class.include(Helpers::ClassMethods)
16
+ end
17
+ end
18
+
19
+ end # ... Allow
20
+ end # ... AsMethod
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+
5
+ module AsMethod
6
+ class FindOrDefineModule
7
+ def self.call(**args)
8
+ new.call(**args)
9
+ end
10
+
11
+ def call(module_template:, module_name:, vars:)
12
+ @vars = vars
13
+ @module_name = module_name
14
+ @module_template = module_template
15
+
16
+ instance_eval(generate_module_source_code) unless module_exists?
17
+
18
+ includable_module
19
+ end
20
+
21
+ private
22
+
23
+ def generate_module_source_code
24
+ payload = @vars.merge(module_name: @module_name)
25
+ ::ERB.new(@module_template).result_with_hash(payload)
26
+ end
27
+
28
+ def includable_module
29
+ Object.const_get(@module_name)
30
+ end
31
+
32
+ def module_exists?
33
+ Object.const_defined?(@module_name)
34
+ end
35
+ end # ... FindOrDefineModule
36
+ end # ... AsMethod
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AsMethod
4
+ class GetServiceObject
5
+ AMBIGUOUS_NAME_ERROR_MSG = <<-MSG
6
+ Ambiguous name. %s has both class and instance methods named %s.
7
+ Please use '::method_name' or '#method_name' to specify which one you want.
8
+ MSG
9
+
10
+ def self.call(obj, method_name)
11
+ new.call(obj, method_name)
12
+ end
13
+
14
+ def call(obj, method_name)
15
+ raise ArgumentError, "expected #{obj} to be a Module or Class" unless obj.is_a?(Module)
16
+
17
+ @obj = obj
18
+ @method_name = method_name
19
+
20
+ if method_name[0, 2] == "::"
21
+ get_method(nil, method_name[2..-1])
22
+ elsif method_name[0] == "#"
23
+ get_method(method_name[1..-1], nil)
24
+ else
25
+ get_method(method_name, method_name)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def get_instance_method(name)
32
+ return unless name
33
+ return unless @obj.method_defined?(name) || @obj.private_method_defined?(name)
34
+
35
+ @obj.instance_method(name)
36
+ end
37
+
38
+ def get_class_method(name)
39
+ return unless name
40
+ return unless @obj.singleton_class.method_defined?(name) || @obj.singleton_class.private_method_defined?(name)
41
+
42
+ @obj.method(name)
43
+ end
44
+
45
+ def get_method(instance_method_name, class_method_name)
46
+ imethod = get_instance_method(instance_method_name)
47
+ cmethod = get_class_method(class_method_name)
48
+
49
+ if [imethod, cmethod].none?
50
+ raise NameError, "undefined method #{@method_name.inspect} for #{@obj.inspect}"
51
+ end
52
+
53
+ if [imethod, cmethod].all?
54
+ raise NameError, format(AMBIGUOUS_NAME_ERROR_MSG, @obj.inspect, @method_name.inspect)
55
+ end
56
+
57
+ (cmethod || imethod).owner.instance_variable_get(:@_injectable_object)
58
+ end
59
+ end # ... GetServiceObject
60
+ end # ... AsMethod
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AsMethod
4
+ module Helpers
5
+
6
+ module InstanceMethods
7
+ def service_object_for(method_name)
8
+ self.class.service_object_for(method_name)
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ def service_object_for(method_name)
14
+ GetServiceObject.call(self, method_name)
15
+ end
16
+
17
+ # rubocop:disable Metrics/AbcSize
18
+ def as_method(object, name: nil, access: :private)
19
+ raise ArgumentError unless %w[private public protected].include?(access.to_s)
20
+
21
+ ValidateServiceObject.call(object)
22
+
23
+ # generate method name from object, if none given
24
+ method_name = name&.to_s || MethodName::GenerateFromClassName.call(object.name)
25
+
26
+ MethodName::Validate.call(method_name)
27
+
28
+ module_name = "::#{object.name}::As#{access.capitalize}Method__#{ModuleName::GenerateFromSnakeCase.call(method_name)}" # rubocop:disable Layout/LineLength
29
+
30
+ # define module, or return existing module:
31
+ includable_module = FindOrDefineModule.call \
32
+ module_template: File.read(File.join(__dir__, "templates", "includable_module.rb.erb")),
33
+ module_name: module_name,
34
+ vars: {
35
+ object: object,
36
+ method_name: method_name,
37
+ method_access: access,
38
+ }
39
+
40
+ # return generated module ready for inclusion:
41
+ included_modules.include?(includable_module) ? Kernel : includable_module
42
+ end
43
+ # rubocop:enable Metrics/AbcSize
44
+
45
+ end # ... ClassMethods
46
+ end # ... Helpers
47
+ end # ... AsMethod
@@ -2,15 +2,15 @@
2
2
 
3
3
  module AsMethod
4
4
  module MethodName
5
- module GenerateFromModuleName
5
+ module GenerateFromClassName
6
6
 
7
7
  def self.call(module_name)
8
8
  ModuleName::StripNamespace.call(module_name)
9
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
10
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
9
+ .gsub(/([A-Z]+)([A-Z][a-z])/, %q(\1_\2))
10
+ .gsub(/([a-z\d])([A-Z])/, %q(\1_\2))
11
11
  .downcase
12
12
  end
13
13
 
14
- end # ... GenerateFromModuleName
14
+ end # ... GenerateFromClassName
15
15
  end # ... MethodName
16
16
  end # ... AsMethod
@@ -2,19 +2,19 @@
2
2
 
3
3
  module AsMethod
4
4
  module MethodName
5
- module ValidateMethodName
5
+ module Validate
6
6
 
7
- REGULAR_NAME_REGEX = /\A[a-z_]+[a-z0-9_]*[?!=]{0,1}\z/
7
+ REGULAR_NAME_REGEX = /\A[a-z_]+[a-z0-9_]*[?!=]{0,1}\z/.freeze
8
8
 
9
- SPECIAL_NAMES = %w{[] ! ~ + ** - * / % << >> & | ^ < <= >= > == === != =~ !~ <=>}
9
+ SPECIAL_NAMES = %w{[] ! ~ + ** - * / % << >> & | ^ < <= >= > == === != =~ !~ <=>}.freeze
10
10
 
11
11
  def self.call(name)
12
12
  return true if name.to_s =~ REGULAR_NAME_REGEX
13
13
  return true if SPECIAL_NAMES.include?(name.to_s)
14
-
15
- false
14
+
15
+ fail ArgumentError, "invalid method name #{name.inspect}"
16
16
  end
17
17
 
18
- end # ... ValidateMethodName
18
+ end # ... Validate
19
19
  end # ... MethodName
20
- end # ... AsMethod
20
+ end # ... AsMethod
@@ -2,8 +2,7 @@
2
2
 
3
3
  module AsMethod
4
4
  module ModuleName
5
- module GenerateFromUnderscored
6
-
5
+ module GenerateFromSnakeCase
7
6
  REPLACEMENTS = {
8
7
  "-" => "_Min",
9
8
  "!" => "_Exc",
@@ -25,12 +24,13 @@ module AsMethod
25
24
 
26
25
  def self.call(string)
27
26
  return unless string
28
-
27
+
28
+ escaped_replacements = REPLACEMENTS.keys.map { Regexp.escape(_1) }
29
29
  string.to_s
30
- .gsub(/(?:_|(^))([a-z\d]{1})/) { "#{$1}#{$2.capitalize}" }
30
+ .sub(/^(_|#{escaped_replacements.join('|')})/, "SPECIAL\\1")
31
+ .gsub(/(^|_)([a-z])/) { ::Regexp.last_match(2).capitalize.to_s }
31
32
  .gsub(/[#{Regexp.escape(REPLACEMENTS.keys.join)}]/, REPLACEMENTS)
32
33
  end
33
-
34
- end # ... GenerateFromUnderscored
34
+ end # ... GenerateFromSnakeCase
35
35
  end # ... ModuleName
36
- end # ... AsMethod
36
+ end
@@ -4,8 +4,10 @@ module AsMethod
4
4
  module ModuleName
5
5
  module StripNamespace
6
6
 
7
- def self.call(module_or_class)
8
- module_or_class.to_s.match(/[^:]+\z/)&.to_s
7
+ def self.call(module_or_class_name)
8
+ name = String(module_or_class_name)
9
+ index = name.rindex("::")
10
+ index ? name[(index + 2)..-1] : name
9
11
  end
10
12
 
11
13
  end # ... StripNamespace
@@ -3,9 +3,10 @@
3
3
  # Usage:
4
4
  #
5
5
  # Require this file to add #as_method class method to all classes:
6
- # require 'as_method/setup'
6
+ # require "as_method/setup"
7
7
  #
8
8
 
9
- unless Object.singleton_class.included_modules.include?(AsMethod)
10
- Object.extend AsMethod
11
- end
9
+ require "as_method"
10
+
11
+ Module.extend(AsMethod::Allow)
12
+ Object.extend(AsMethod::Allow)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AsMethod
4
+ module ValidateServiceObject
5
+
6
+ def self.call(module_or_class)
7
+ unless module_or_class.is_a?(Module)
8
+ fail TypeError, "#{module_or_class} must be a Class or a Module"
9
+ end
10
+
11
+ return if module_or_class.respond_to?(:call)
12
+
13
+ fail NoMethodError, "Expected #{module_or_class} to respond to #call method"
14
+ end
15
+
16
+ end # ... ValidateServiceObject
17
+ end # ... AsMethod
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AsMethod
4
4
 
5
- VERSION = "0.1.1"
5
+ VERSION = "0.3.0"
6
6
 
7
7
  end
data/lib/as_method.rb CHANGED
@@ -1,29 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AsMethod
4
- autoload :DefineIncludableModule, "as_method/define_includable_module"
5
- autoload :FindOrDefineIncludableModule, "as_method/find_or_define_includable_module"
6
- autoload :RegistrationMethods, "as_method/registration_methods"
4
+ autoload :Allow, "as_method/allow"
5
+ autoload :Helpers, "as_method/helpers"
6
+ autoload :FindOrDefineModule, "as_method/find_or_define_module"
7
+ autoload :ValidateServiceObject, "as_method/validate_service_object"
8
+ autoload :GetServiceObject, "as_method/get_service_object"
7
9
  autoload :VERSION, "as_method/version"
8
10
 
9
11
  module ModuleName
10
- autoload :GenerateForIncludableModule, "as_method/module_name/generate_for_includable_module"
11
- autoload :GenerateFromUnderscored, "as_method/module_name/generate_from_underscored"
12
+ autoload :GenerateFromSnakeCase, "as_method/module_name/generate_from_snake_case"
12
13
  autoload :StripNamespace, "as_method/module_name/strip_namespace"
13
14
  end
14
15
 
15
16
  module MethodName
16
- autoload :ValidateMethodName, "as_method/method_name/validate_method_name"
17
- autoload :GenerateFromModuleName, "as_method/method_name/generate_from_module_name"
17
+ autoload :Validate, "as_method/method_name/validate"
18
+ autoload :GenerateFromClassName, "as_method/method_name/generate_from_class_name"
18
19
  end
19
20
 
20
- def as_method(service_object, name: nil)
21
- includable_module = FindOrDefineIncludableModule.call(service_object, name)
22
- unless self.included_modules.include?(includable_module)
23
- includable_module
24
- else
25
- Kernel # a bit faster
26
- end
27
-
28
- end
29
21
  end # ... AsMethod
metadata CHANGED
@@ -1,44 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: as_method
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Gorodulin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-06 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rspec
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '3.2'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '3.2'
27
- - !ruby/object:Gem::Dependency
28
- name: pry
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.14'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.14'
41
- description: Make callable Service Objects includable as methods
11
+ date: 2024-01-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Bring Service Objects to your classes as methods.
42
14
  email:
43
15
  - ru.hostmaster@gmail.com
44
16
  executables: []
@@ -49,15 +21,16 @@ files:
49
21
  - LICENSE
50
22
  - README.md
51
23
  - lib/as_method.rb
52
- - lib/as_method/define_includable_module.rb
53
- - lib/as_method/find_or_define_includable_module.rb
54
- - lib/as_method/method_name/generate_from_module_name.rb
55
- - lib/as_method/method_name/validate_method_name.rb
56
- - lib/as_method/module_name/generate_for_includable_module.rb
57
- - lib/as_method/module_name/generate_from_underscored.rb
24
+ - lib/as_method/allow.rb
25
+ - lib/as_method/find_or_define_module.rb
26
+ - lib/as_method/get_service_object.rb
27
+ - lib/as_method/helpers.rb
28
+ - lib/as_method/method_name/generate_from_class_name.rb
29
+ - lib/as_method/method_name/validate.rb
30
+ - lib/as_method/module_name/generate_from_snake_case.rb
58
31
  - lib/as_method/module_name/strip_namespace.rb
59
- - lib/as_method/registration_methods.rb
60
32
  - lib/as_method/setup.rb
33
+ - lib/as_method/validate_service_object.rb
61
34
  - lib/as_method/version.rb
62
35
  homepage: https://github.com/gorodulin/as_method
63
36
  licenses:
@@ -74,14 +47,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
74
47
  requirements:
75
48
  - - ">="
76
49
  - !ruby/object:Gem::Version
77
- version: 2.0.0
50
+ version: '2.3'
78
51
  required_rubygems_version: !ruby/object:Gem::Requirement
79
52
  requirements:
80
53
  - - ">="
81
54
  - !ruby/object:Gem::Version
82
55
  version: '0'
83
56
  requirements: []
84
- rubygems_version: 3.1.6
57
+ rubygems_version: 3.4.22
85
58
  signing_key:
86
59
  specification_version: 4
87
60
  summary: Call Service Objects with ease. Include them to your classes as methods!
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AsMethod
4
- module DefineIncludableModule
5
-
6
- PASS = if RUBY_VERSION < "2.7"
7
- "*args, &block"
8
- else
9
- "..."
10
- end
11
-
12
- def self.call(includable_module_name, service_object_class, method_name)
13
- puts "-- DefineIncludableModule #{includable_module_name}"
14
- code = <<~RUBY
15
- module #{includable_module_name}
16
-
17
- def self.ruby2_keywords(*)
18
- puts "-- ruby2_keywords"
19
- end if RUBY_VERSION < "2.7"
20
-
21
- ruby2_keywords def #{method_name}(*args, &block)
22
- self.class.registered_service_objects[:"#{method_name}"].call(*args, &block)
23
- end
24
-
25
- def self.included(base)
26
- if base.instance_of?(Module)
27
- fail TypeError, "Can't be included into Module \#{base.inspect}"
28
- end
29
- unless base.included_modules.include?(RegistrationMethods)
30
- #puts "-- included #{includable_module_name} into \#{base}"
31
- base.include RegistrationMethods
32
- end
33
- base.register_service_object(:"#{method_name}", ::#{service_object_class})
34
- end
35
-
36
- def self.extended(_base)
37
- raise "Do not extend, include!"
38
- end
39
- end
40
- RUBY
41
- instance_eval code
42
- end
43
-
44
- end # ... DefineIncludableModule
45
- end # ... AsMethod
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AsMethod
4
- class FindOrDefineIncludableModule
5
-
6
- def self.call(service_object, method_name)
7
- new.call(service_object, method_name)
8
- end
9
-
10
- def call(service_object, method_name)
11
- # Note: order matters:
12
- self.service_object = service_object
13
- self.method_name = method_name
14
- self.includable_module_name = generate_includable_module_name(service_object, method_name)
15
-
16
- define_includable_module unless Object.const_defined?(includable_module_name)
17
-
18
- Object.const_get(includable_module_name)
19
- end
20
-
21
- private
22
-
23
- attr_accessor :includable_module_name
24
- attr_reader :method_name
25
- attr_reader :service_object
26
-
27
- def define_includable_module
28
- DefineIncludableModule.call(includable_module_name, service_object, method_name)
29
- end
30
-
31
- def generate_method_name_from_so_name
32
- MethodName::GenerateFromModuleName.call(service_object.name)
33
- end
34
-
35
- def generate_includable_module_name(service_object, method_name)
36
- ModuleName::GenerateForIncludableModule.call(service_object, method_name)
37
- end
38
-
39
- def method_name=(name)
40
- validate_method_name!(name.to_s) if name
41
-
42
- @method_name = name&.to_s || generate_method_name_from_so_name
43
- end
44
-
45
- def service_object=(module_or_class)
46
- unless module_or_class.respond_to?(:call)
47
- fail NoMethodError, "Expected #{module_or_class} to respond to #call method"
48
- end
49
- unless module_or_class.is_a?(Module)
50
- fail TypeError, "#{module_or_class} must be a Class or a Module"
51
- end
52
- @service_object = module_or_class
53
- end
54
-
55
- def validate_method_name!(name)
56
- return if MethodName::ValidateMethodName.call(name)
57
-
58
- fail NameError, "wrong method name #{name.inspect}"
59
- end
60
-
61
- end # ... FindOrDefineIncludableModule
62
- end # ... AsMethod
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AsMethod
4
- module ModuleName
5
- module GenerateForIncludableModule
6
-
7
- def self.call(module_or_class, method_name = nil)
8
- part = GenerateFromUnderscored.call(method_name) || StripNamespace.call(module_or_class)
9
-
10
- "::#{module_or_class}::As#{part}Method"
11
- end
12
-
13
- end # ... GenerateForIncludableModule
14
- end # ... ModuleName
15
- end # ... AsMethod
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AsMethod
4
- module RegistrationMethods
5
-
6
- module ClassMethods
7
- def registered_service_objects
8
- @registered_service_objects ||= {}
9
- end
10
-
11
- def register_service_objects(hash)
12
- hash.each { |name, so| register_service_object(name, so) }
13
- end
14
-
15
- def register_service_object(name, so)
16
- registered_service_objects[name.to_sym]&.tap do |registered_so|
17
- return if so == registered_so
18
- raise "#{so} clashes with #{registered_so} in #{self}" if so != registered_so
19
- end
20
-
21
- # puts "--- register #{self.name}##{name} => #{so}#call"
22
- registered_service_objects[name.to_sym] = so
23
- end
24
- end # ... ClassMethods
25
-
26
- def self.included(base)
27
- return if base.singleton_class.included_modules.include?(ClassMethods)
28
-
29
- puts "-- #{base.name} extend with RegistrationMethods::ClassMethods"
30
- base.extend ClassMethods
31
- end
32
-
33
- end # ... RegistrationMethods
34
- end # ... AsMethod