core-extension 0.2.0 → 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 +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/core/extension/behavior.rb +35 -3
- data/lib/core/extension/dependency.rb +35 -40
- data/lib/core/extension/version.rb +1 -1
- data/lib/is/extension.rb +42 -11
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02a2bc3087e71c3fc19d9f0c20210833a2a8bd88cf76f6187fade6e389eadf14
|
4
|
+
data.tar.gz: 8e38b249e3e3e5badcd6f9e6658d967f96f63ab837d563ca5e97f0cc408ee7a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38f391788aef874938c0e69dd95eaa24fee62737dbd5744a3bfafe0813e52189266ef079808a61d29c93688963b8eef1ef4bad9c38dbe2fcd38fb4ea468a3174
|
7
|
+
data.tar.gz: a41f51ba2b22432e4cd8505065f3e44fa57d1ba5c38cbc5c7b7fb362698cf47580dca2515b0b35fc0a2d2bd2fa5c498ab7faf1e7a67ada66f5591fb551d32954
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## [v0.3.0](https://github.com/metabahn/corerb/releases/tag/2021-07-15)
|
2
|
+
|
3
|
+
*released on 2021-07-15*
|
4
|
+
|
5
|
+
* `chg` [#72](https://github.com/metabahn/corerb/pull/72) Rename extension dependency flags ([bryanp](https://github.com/bryanp))
|
6
|
+
* `chg` [#71](https://github.com/metabahn/corerb/pull/71) Rename Is::Extension::applied to applies ([bryanp](https://github.com/bryanp))
|
7
|
+
* `chg` [#68](https://github.com/metabahn/corerb/pull/68) Pass the extension scope to apply blocks ([bryanp](https://github.com/bryanp))
|
8
|
+
* `chg` [#67](https://github.com/metabahn/corerb/pull/67) Refactor extend support for extensions ([bryanp](https://github.com/bryanp))
|
9
|
+
* `chg` [#66](https://github.com/metabahn/corerb/pull/66) Support extending classes with extensions ([bryanp](https://github.com/bryanp))
|
10
|
+
|
1
11
|
## [v0.2.0](https://github.com/metabahn/corerb/releases/tag/2021-07-07)
|
2
12
|
|
3
13
|
*released on 2021-07-07*
|
@@ -12,9 +12,17 @@ module Core
|
|
12
12
|
@module = build_module(&block)
|
13
13
|
end
|
14
14
|
|
15
|
-
# [public] Applies this behavior to an object.
|
15
|
+
# [public] Applies this behavior to an object via extend.
|
16
16
|
#
|
17
|
-
def
|
17
|
+
def apply_extend(object)
|
18
|
+
if force? || unapplied?(object)
|
19
|
+
object.extend(@module)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# [public] Applies this behavior to an object via include.
|
24
|
+
#
|
25
|
+
def apply_include(object)
|
18
26
|
if force? || unapplied?(object)
|
19
27
|
object.include(@module)
|
20
28
|
end
|
@@ -34,11 +42,35 @@ module Core
|
|
34
42
|
|
35
43
|
private def build_module(&block)
|
36
44
|
Module.new {
|
45
|
+
define_singleton_method(:extended) do |base|
|
46
|
+
arguments = {
|
47
|
+
extended: true,
|
48
|
+
included: false
|
49
|
+
}
|
50
|
+
|
51
|
+
base.class_exec(**Behavior.conditional_keyword_arguments(arguments, block), &block)
|
52
|
+
end
|
53
|
+
|
37
54
|
define_singleton_method(:included) do |base|
|
38
|
-
|
55
|
+
arguments = {
|
56
|
+
extended: false,
|
57
|
+
included: true
|
58
|
+
}
|
59
|
+
|
60
|
+
base.class_exec(**Behavior.conditional_keyword_arguments(arguments, block), &block)
|
39
61
|
end
|
40
62
|
}
|
41
63
|
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
def conditional_keyword_arguments(arguments, callable)
|
67
|
+
arguments.keep_if { |key, _value|
|
68
|
+
callable.parameters.any? { |type, name|
|
69
|
+
(type == :key || type == :keyreq || type == :keyrest) && name == key
|
70
|
+
}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
42
74
|
end
|
43
75
|
end
|
44
76
|
end
|
@@ -6,70 +6,71 @@ module Core
|
|
6
6
|
#
|
7
7
|
# flags - Changes how the dependencies are applied. Possible values include:
|
8
8
|
#
|
9
|
-
# * `:
|
9
|
+
# * `:definition` - Extends the definition of the including object.
|
10
10
|
#
|
11
|
-
# * `:
|
11
|
+
# * `:implementation` - Extends the implementation of the including object.
|
12
12
|
#
|
13
|
-
# Dependencies are applied with the `:
|
13
|
+
# Dependencies are applied with the `:implementation` flag by default.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# dependency - The dependency to be applied to objects, following the rules defined by flags.
|
16
16
|
#
|
17
|
-
# prepend - If `true`, methods will be prepended
|
18
|
-
#
|
19
|
-
# block - If passed, defines an anonymous module as a dependency.
|
17
|
+
# prepend - If `true`, methods will be prepended.
|
20
18
|
#
|
21
19
|
class Dependency
|
22
|
-
ALLOWED_FLAGS = %i[
|
20
|
+
ALLOWED_FLAGS = %i[definition implementation].freeze
|
21
|
+
ALLOWED_FLAGS_STRING = ALLOWED_FLAGS.map { |allowed_flag|
|
22
|
+
"`#{allowed_flag.inspect}'"
|
23
|
+
}.join(", ").freeze
|
23
24
|
|
24
|
-
def initialize(*flags,
|
25
|
+
def initialize(*flags, dependency:, prepend: false)
|
25
26
|
flags = flags.map(&:to_sym)
|
26
27
|
enforce_allowed_flags(flags)
|
27
28
|
|
28
29
|
@flags = flags
|
29
|
-
@
|
30
|
+
@dependency = dependency
|
30
31
|
@prepend = prepend
|
31
|
-
|
32
|
-
@
|
32
|
+
@definition = @flags.include?(:definition)
|
33
|
+
@implementation = @flags.include?(:implementation) || (!definition? && !prepend?)
|
33
34
|
end
|
34
35
|
|
35
|
-
# [public] Apply the defined dependencies to an object.
|
36
|
+
# [public] Apply the defined dependencies to an object via extend.
|
36
37
|
#
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def apply_extend(object)
|
39
|
+
if prepend?
|
40
|
+
object.singleton_class.prepend(@dependency) if implementation? || definition?
|
41
|
+
elsif definition? || implementation?
|
42
|
+
object.extend(@dependency)
|
43
|
+
end
|
44
|
+
end
|
41
45
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
# [public] Apply the defined dependencies to an object via include.
|
47
|
+
#
|
48
|
+
def apply_include(object)
|
49
|
+
if prepend?
|
50
|
+
object.prepend(@dependency) if implementation?
|
51
|
+
object.singleton_class.prepend(@dependency) if definition?
|
52
|
+
else
|
53
|
+
object.include(@dependency) if implementation?
|
54
|
+
object.extend(@dependency) if definition?
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
53
|
-
private def
|
54
|
-
@
|
58
|
+
private def implementation?
|
59
|
+
@implementation == true
|
55
60
|
end
|
56
61
|
|
57
|
-
private def
|
58
|
-
@
|
62
|
+
private def definition?
|
63
|
+
@definition == true
|
59
64
|
end
|
60
65
|
|
61
66
|
private def prepend?
|
62
67
|
@prepend == true
|
63
68
|
end
|
64
69
|
|
65
|
-
private def build_module(&block)
|
66
|
-
Module.new(&block)
|
67
|
-
end
|
68
|
-
|
69
70
|
private def enforce_allowed_flags(flags)
|
70
71
|
flags.each do |flag|
|
71
72
|
unless allowed_flag?(flag)
|
72
|
-
raise ArgumentError, "Expected flag `#{flag.inspect}' to be one of: #{
|
73
|
+
raise ArgumentError, "Expected flag `#{flag.inspect}' to be one of: #{ALLOWED_FLAGS_STRING}"
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
@@ -77,12 +78,6 @@ module Core
|
|
77
78
|
private def allowed_flag?(flag)
|
78
79
|
ALLOWED_FLAGS.include?(flag)
|
79
80
|
end
|
80
|
-
|
81
|
-
private def allowed_flags_string
|
82
|
-
ALLOWED_FLAGS.map { |allowed_flag|
|
83
|
-
"`#{allowed_flag.inspect}'"
|
84
|
-
}.join(", ")
|
85
|
-
end
|
86
81
|
end
|
87
82
|
end
|
88
83
|
end
|
data/lib/is/extension.rb
CHANGED
@@ -15,20 +15,39 @@ module Is
|
|
15
15
|
|
16
16
|
# [public] Define a module to be extended or included into objects that include this extension.
|
17
17
|
#
|
18
|
+
# TODO: These flags almost need different names, since instance extensions could technically end up on a class.
|
19
|
+
# Name them by their intended use? Like a definition and usage lifecycle or something.
|
20
|
+
#
|
21
|
+
# Maybe `definition` and `implementation`?
|
22
|
+
#
|
18
23
|
def extends(*flags, dependencies: [], prepend: false, &block)
|
19
|
-
|
24
|
+
dependencies.each do |dependency|
|
25
|
+
defined_dependencies << Core::Extension::Dependency.new(*flags, dependency: dependency, prepend: prepend)
|
26
|
+
end
|
27
|
+
|
28
|
+
if block
|
29
|
+
defined_dependencies << Core::Extension::Dependency.new(*flags, dependency: Module.new(&block), prepend: prepend)
|
30
|
+
end
|
20
31
|
end
|
21
32
|
|
22
33
|
# [public] Define behavior to be evaled on objects that include this extension.
|
23
34
|
#
|
24
|
-
def
|
35
|
+
def applies(force: false, &block)
|
25
36
|
defined_behaviors << Core::Extension::Behavior.new(force: force, &block)
|
26
37
|
end
|
27
38
|
|
39
|
+
def extended(base)
|
40
|
+
enforce_allowed_types(base)
|
41
|
+
extend_defined_dependencies(base)
|
42
|
+
extend_defined_behaviors(base)
|
43
|
+
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
28
47
|
def included(base)
|
29
48
|
enforce_allowed_types(base)
|
30
|
-
|
31
|
-
|
49
|
+
include_defined_dependencies(base)
|
50
|
+
include_defined_behaviors(base)
|
32
51
|
|
33
52
|
super
|
34
53
|
end
|
@@ -51,15 +70,27 @@ module Is
|
|
51
70
|
}
|
52
71
|
end
|
53
72
|
|
54
|
-
private def
|
73
|
+
private def extend_defined_behaviors(object)
|
74
|
+
defined_behaviors.each do |behavior|
|
75
|
+
behavior.apply_extend(object)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private def extend_defined_dependencies(object)
|
80
|
+
defined_dependencies.each do |dependency|
|
81
|
+
dependency.apply_extend(object)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private def include_defined_behaviors(object)
|
55
86
|
defined_behaviors.each do |behavior|
|
56
|
-
behavior.
|
87
|
+
behavior.apply_include(object)
|
57
88
|
end
|
58
89
|
end
|
59
90
|
|
60
|
-
private def
|
61
|
-
|
62
|
-
|
91
|
+
private def include_defined_dependencies(object)
|
92
|
+
defined_dependencies.each do |dependency|
|
93
|
+
dependency.apply_include(object)
|
63
94
|
end
|
64
95
|
end
|
65
96
|
|
@@ -71,8 +102,8 @@ module Is
|
|
71
102
|
@__defined_behaviors ||= []
|
72
103
|
end
|
73
104
|
|
74
|
-
private def
|
75
|
-
@
|
105
|
+
private def defined_dependencies
|
106
|
+
@__defined_dependencies ||= []
|
76
107
|
end
|
77
108
|
end
|
78
109
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: core-extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Powell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Create mixins with superpowers.
|
14
14
|
email: bryan@metabahn.com
|