toritori 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -12
- data/lib/toritori/factory.rb +21 -20
- data/lib/toritori/version.rb +1 -1
- data/lib/toritori.rb +2 -8
- metadata +2 -4
- data/lib/toritori/factory/instantiator.rb +0 -24
- data/lib/toritori/factory/subclass.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: 47da200bc6b1c00517984ac052c3f3c1f3eab8dcfb9444158a893fb3e254bef4
|
4
|
+
data.tar.gz: 11da3242909586815d5c564c9ab80b04ccdd66b0cc02b96f61d416758c265c3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4887c90e93f2a13c8942b6b7028f957dead740214ebdadc4717f71ef5005a7dd672c3559b9523bc52e4e741c94cfba637ec4b27215eb31c1bf003a6a027130fd
|
7
|
+
data.tar.gz: cf38a85c4d6efd4989f49740dfeb373780325b88007d34bbb18841b7efb6987c924d80516229cf6c17a389471ca772b1eafe26fad792c752b31eda65e68a41bc
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
## [0.2.0] - 2023-07-05
|
2
|
+
|
3
|
+
### Improved
|
4
|
+
* Performace and memory usage
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
* The way to specify different method to create object (default `new`)
|
8
|
+
* `factory.subclass` is a method now, not a "value object"
|
9
|
+
|
10
|
+
## [0.1.0] - 2023-05-18
|
11
|
+
|
12
|
+
- Initial release
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -66,10 +66,7 @@ The library defaults is to use `new` method for instantiation and bypass paramet
|
|
66
66
|
class MyAbstractFactory
|
67
67
|
include Toritori
|
68
68
|
|
69
|
-
factory :file, produces: File
|
70
|
-
# Every method is called on File
|
71
|
-
open(file_name, 'r')
|
72
|
-
end
|
69
|
+
factory :file, produces: File, creation_method: :open
|
73
70
|
end
|
74
71
|
|
75
72
|
MyAbstractFactory.file_factory.create('/dev/null') # => #<File @path='/dev/null'>
|
@@ -112,11 +109,6 @@ class ModernFactory < MyAbstractFactory
|
|
112
109
|
|
113
110
|
attr_reader :wifi
|
114
111
|
end
|
115
|
-
|
116
|
-
# Notify factory about new way to create objects
|
117
|
-
chair_factory.subclass.init do |width, wifi:|
|
118
|
-
new(width, wifi)
|
119
|
-
end
|
120
112
|
end
|
121
113
|
|
122
114
|
modern_chair = ModernFactory.chair_factory.create(2500, wifi: false)
|
@@ -127,12 +119,16 @@ The subclass (`ModernFactory`) will gen a copy of `factories` so you can customi
|
|
127
119
|
Sometimes when subclass definition is big it is better to put it into a separate file. To make the library to use that sub-class:
|
128
120
|
```ruby
|
129
121
|
class ModernTable < MyAbstractFactory.table_factory.base_class
|
130
|
-
# ...
|
131
|
-
end
|
122
|
+
# ... omitted ...
|
123
|
+
end
|
132
124
|
|
133
125
|
class ModernFactory < MyAbstractFactory
|
134
126
|
# Update initialize method
|
135
|
-
table_factory.subclass
|
127
|
+
table_factory.subclass(produces: ModernTable, creation_method: :produce) do
|
128
|
+
def self.produce(...)
|
129
|
+
new(...)
|
130
|
+
end
|
131
|
+
end
|
136
132
|
|
137
133
|
table_factory.create # => #<ModernTable>
|
138
134
|
end
|
data/lib/toritori/factory.rb
CHANGED
@@ -3,37 +3,38 @@
|
|
3
3
|
module Toritori
|
4
4
|
# Generates module that adds support for objects creation
|
5
5
|
class Factory
|
6
|
-
attr_reader :name
|
7
|
-
|
8
|
-
def cached_instantiator(subclass)
|
9
|
-
id = [subclass.base_class.object_id, subclass.init.object_id].join('_')
|
10
|
-
@cache ||= ::Hash.new do |h, key|
|
11
|
-
h[key] = Instantiator.new(subclass)
|
12
|
-
end
|
13
|
-
@cache[id]
|
14
|
-
end
|
15
|
-
|
16
6
|
def copy
|
17
|
-
self.class.new(name, base_class: base_class,
|
7
|
+
self.class.new(@name, base_class: @base_class, creation_method: @creation_method)
|
18
8
|
end
|
19
9
|
|
20
|
-
def initialize(name, base_class: nil,
|
10
|
+
def initialize(name, base_class: nil, creation_method: :new)
|
21
11
|
@name = name
|
22
|
-
@
|
12
|
+
@base_class = base_class
|
13
|
+
@creation_method = creation_method
|
23
14
|
end
|
24
15
|
|
25
|
-
def subclass(&block)
|
26
|
-
|
27
|
-
|
28
|
-
@
|
16
|
+
def subclass(produces: nil, creation_method: @creation_method, &block)
|
17
|
+
@base_class = check_base_class(produces) || @base_class
|
18
|
+
@base_class = Class.new(@base_class, &block) if block
|
19
|
+
@creation_method = creation_method
|
29
20
|
end
|
30
21
|
|
31
22
|
def create(*args, **kwargs, &block)
|
32
|
-
|
23
|
+
return @base_class.new(*args, **kwargs, &block) if @creation_method == :new
|
24
|
+
|
25
|
+
@base_class.public_send(@creation_method, *args, **kwargs, &block)
|
33
26
|
end
|
34
27
|
|
35
|
-
|
36
|
-
|
28
|
+
private
|
29
|
+
|
30
|
+
def check_base_class(subclass_const = nil)
|
31
|
+
return unless subclass_const
|
32
|
+
|
33
|
+
::Kernel.raise NotAClassError unless subclass_const.is_a?(::Class)
|
34
|
+
|
35
|
+
::Kernel.raise(SubclassError, "must be a subclass of #{@base_class.inspect}") unless subclass_const <= @base_class
|
36
|
+
|
37
|
+
subclass_const
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
data/lib/toritori/version.rb
CHANGED
data/lib/toritori.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'toritori/factory/instantiator'
|
4
|
-
require 'toritori/factory/subclass'
|
5
3
|
require 'toritori/factory'
|
6
4
|
require 'toritori/version'
|
7
5
|
|
@@ -21,8 +19,8 @@ module Toritori
|
|
21
19
|
@factories = other
|
22
20
|
end
|
23
21
|
|
24
|
-
def factory(name, produces: Class.new, &block)
|
25
|
-
factories[name] = Toritori::Factory.new(name, base_class: produces, &block)
|
22
|
+
def factory(name, produces: Class.new, creation_method: :new, &block)
|
23
|
+
factories[name] = Toritori::Factory.new(name, base_class: produces, creation_method: creation_method, &block)
|
26
24
|
define_singleton_method(:"#{name}_factory") { factories[name] }
|
27
25
|
end
|
28
26
|
|
@@ -32,10 +30,6 @@ module Toritori
|
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
35
|
-
def self.default_init
|
36
|
-
@default_init ||= ->(*args, **kwargs, &block) { new(*args, **kwargs, &block) }
|
37
|
-
end
|
38
|
-
|
39
33
|
def self.included(receiver)
|
40
34
|
receiver.extend ClassMethods
|
41
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toritori
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrii Baran
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Create factories with DSL
|
14
14
|
email:
|
@@ -32,8 +32,6 @@ files:
|
|
32
32
|
- bin/setup
|
33
33
|
- lib/toritori.rb
|
34
34
|
- lib/toritori/factory.rb
|
35
|
-
- lib/toritori/factory/instantiator.rb
|
36
|
-
- lib/toritori/factory/subclass.rb
|
37
35
|
- lib/toritori/version.rb
|
38
36
|
- toritori.gemspec
|
39
37
|
homepage: https://github.com/andriy-baran/toritori
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Toritori
|
4
|
-
class Factory
|
5
|
-
# Utility class that evaluates initalization procs
|
6
|
-
class Instantiator < BasicObject
|
7
|
-
def initialize(subclass)
|
8
|
-
@subclass = subclass
|
9
|
-
@type = subclass.base_class
|
10
|
-
define_singleton_method(:__create__, &subclass.init)
|
11
|
-
end
|
12
|
-
|
13
|
-
def method_missing(method, *args, **kwargs, &block)
|
14
|
-
return super unless @type.respond_to?(method)
|
15
|
-
|
16
|
-
@type.public_send(method, *args, **kwargs, &block)
|
17
|
-
end
|
18
|
-
|
19
|
-
def respond_to_missing?(method, include_private = false)
|
20
|
-
@type.respond_to?(method, include_private) || super
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Toritori
|
4
|
-
class Factory
|
5
|
-
# Utility class that stores initalization procs
|
6
|
-
class Subclass < BasicObject
|
7
|
-
def initialize(base_class, init)
|
8
|
-
@init = init || ::Toritori.default_init
|
9
|
-
@base_class = base_class
|
10
|
-
end
|
11
|
-
|
12
|
-
def init(&block)
|
13
|
-
return @init unless block
|
14
|
-
|
15
|
-
@init = block
|
16
|
-
end
|
17
|
-
|
18
|
-
def base_class(subclass_const = nil)
|
19
|
-
return @base_class unless subclass_const
|
20
|
-
|
21
|
-
::Kernel.raise NotAClassError unless subclass_const.is_a?(::Class)
|
22
|
-
unless subclass_const <= @base_class
|
23
|
-
::Kernel.raise(SubclassError, "must be a subclass of #{@base_class.inspect}")
|
24
|
-
end
|
25
|
-
|
26
|
-
@base_class = subclass_const
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|