as_method 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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