nina 0.1.2 → 0.1.5

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: 28d86e0716c73ae59b0b6ac85076436ae54d1856d072e11114c576cd0b66365e
4
- data.tar.gz: 255f6b2b4ac6b2a6f56f0cbea4fdf38e991494c855cd373417ec99f95af174ac
3
+ metadata.gz: 6a252130b2ce26b317359fa4566edf12fba94042ddb9863fc8c71148a283c718
4
+ data.tar.gz: bb24fa2d53ef3ba45b921cc7a2af366b9e54cd2703681f0cd14210362fe5b473
5
5
  SHA512:
6
- metadata.gz: 745f85388243699c7a2143c8849039b46aad9e343bf3ec005d3f04025d21d4860a7e43969ce06a3ab0357d865bfc4a4efd9fc14c550f551b4aa455a0aa33ab38
7
- data.tar.gz: 6e1a5d9e21e28c3667a56e96b85c1e7c2e6a304ea377d607f1bc1b4b161af4a1e314f4dc28752c2ccc31e982b6cb9b3b0dbf077573dc02c4cd34376baaf4ef75
6
+ metadata.gz: fb97e0c1d28b7dc902366368f770dc3ed7c6f677dd98260dac0caa0a97c16a5d89a09ece6bac74125f7f3a266f4a98baa7a14ff72d163e331b1aa2cb206b0a25
7
+ data.tar.gz: fb26ae5dfac451918af68b16b3f45081559e2e546338fdf8eb0a4b48dcee0f79d4314b3d670b65ac066a472c96ae8c579686ae8f562546a71c2dc81d0bd43f99
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nina (0.1.2)
5
- toritori (= 0.1.0)
4
+ nina (0.1.5)
5
+ toritori (= 0.2.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -58,7 +58,7 @@ GEM
58
58
  json (>= 1.8, < 3)
59
59
  simplecov-html (~> 0.10.0)
60
60
  simplecov-html (0.10.2)
61
- toritori (0.1.0)
61
+ toritori (0.2.1)
62
62
  unicode-display_width (2.4.2)
63
63
 
64
64
  PLATFORMS
@@ -1,49 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'nina/builder/initialization'
4
+ require 'nina/builder/callbacks'
5
+
3
6
  module Nina
4
7
  # Generates module that adds support for objects creation
5
8
  class Assembler
6
- # Adds ability to delegeate methods via method_missing
7
- module MethodMissingDelegation
8
- def method_missing(name, *attrs, &block)
9
- return super unless methods.detect { |m| m == :__predecessor }
10
-
11
- public_send(__predecessor).public_send(name, *attrs, &block)
12
- end
13
-
14
- def respond_to_missing?(method_name, _include_private = false)
15
- return super unless methods.detect { |m| m == :__predecessor }
16
-
17
- public_send(__predecessor).respond_to?(method_name)
18
- end
19
- end
9
+ include Observable
20
10
 
21
- def self.def_accessor(accessor, on:, to:, delegate: false)
22
- on.define_singleton_method(:__predecessor) { accessor }
23
- on.define_singleton_method(accessor) { to }
24
- on.extend(MethodMissingDelegation) if delegate
25
- end
11
+ attr_reader :initialization, :callbacks
26
12
 
27
- def initialize(abstract_factory)
13
+ def initialize(abstract_factory, callbacks = nil)
28
14
  @abstract_factory = abstract_factory
15
+ @initialization = Builder::Initialization.new(@abstract_factory.build_order_list)
16
+ @callbacks = callbacks&.copy || Builder::Callbacks.new(@abstract_factory.build_order_list)
29
17
  end
30
18
 
31
- def inject(build_order, initialization = {}, callbacks: nil, delegate: false)
19
+ def inject(build_order, delegate: false)
32
20
  build_order.each.with_index(-1).inject(nil) do |prev, (name, idx)|
33
21
  object = create_object(name, initialization)
34
- self.class.def_accessor(build_order[idx], on: object, to: prev, delegate: delegate) if prev
35
- callbacks.to_h.fetch(name, []).each { |c| c.call(object) } if callbacks
22
+ setup_relation(object, prev, name, build_order[idx], delegate)
23
+ changed
24
+ notify_observers(name, object)
36
25
  object
37
26
  end
38
27
  end
39
28
 
40
29
  private
41
30
 
31
+ def setup_relation(object, prev, name, accessor, delegate)
32
+ Nina.def_accessor(accessor, on: object, to: prev, delegate: delegate) if prev
33
+ callbacks.to_h[name].each { |c| c.call(object) } if callbacks&.to_h&.key?(name)
34
+ end
35
+
42
36
  def create_object(name, initialization = {})
43
- return @abstract_factory.send("#{name}_factory").create if initialization[name].nil?
37
+ return @abstract_factory.create(name) if initialization.to_h[name].nil?
44
38
 
45
- args, kwargs, block = initialization[name]
46
- @abstract_factory.send("#{name}_factory").create(*args, **kwargs, &block)
39
+ args, kwargs, block = initialization.to_h[name]
40
+ @abstract_factory.create(name, *args, **kwargs, &block)
47
41
  end
48
42
  end
49
43
  end
data/lib/nina/builder.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'nina/builder/initialization'
4
- require 'nina/builder/callbacks'
5
-
6
3
  # This should be a kind of factory that creates complex objects
7
4
  # from simple ones. It should use torirori to create objects.
8
5
  # It also enriches objects with some methods that make them more
@@ -31,8 +28,7 @@ module Nina
31
28
  build_order_list << name
32
29
  super
33
30
  define_singleton_method(name) do |klass = nil, &definition|
34
- factories[__method__].subclass.base_class(klass) if klass
35
- factories[__method__].subclass(&definition) if definition
31
+ factories[__method__].subclass(produces: klass, &definition)
36
32
  end
37
33
  end
38
34
  end
@@ -43,42 +39,37 @@ module Nina
43
39
  @abstract_factory = abstract_factory.include(Toritori).extend(ClassMethods)
44
40
  @abstract_factory.class_eval(&def_block) if def_block
45
41
  @abstract_factory.build_order_list.freeze
46
- @initialization = Initialization.new(@abstract_factory.factories.keys)
47
- @assembler = Assembler.new(@abstract_factory)
48
- @callbacks = callbacks
42
+ @assembler = Assembler.new(@abstract_factory, callbacks)
43
+ @assembler.add_observer(self)
44
+ @observers = []
45
+ end
46
+
47
+ def add_observer(observer)
48
+ @observers << observer
49
49
  end
50
50
 
51
51
  def copy
52
- self.class.new(name, abstract_factory: abstract_factory)
52
+ new_builder = self.class.new(name, abstract_factory: abstract_factory, callbacks: @assembler.callbacks)
53
+ @observers.each { |observer| new_builder.add_observer(observer) }
54
+ new_builder
53
55
  end
54
56
 
55
57
  def with_callbacks(&block)
56
- c = callbacks&.copy || Callbacks.new(abstract_factory.factories.keys)
57
- yield c if block
58
+ yield @assembler.callbacks if block
58
59
 
59
- self.class.new(name, abstract_factory: abstract_factory, callbacks: c)
60
+ copy
60
61
  end
61
62
 
62
63
  def wrap(delegate: false, &block)
63
- yield @initialization if block
64
-
65
- @assembler.inject(
66
- @abstract_factory.build_order_list,
67
- @initialization.to_h,
68
- callbacks: callbacks,
69
- delegate: delegate
70
- )
64
+ yield @assembler.initialization if block
65
+
66
+ @assembler.inject(@abstract_factory.build_order_list, delegate: delegate)
71
67
  end
72
68
 
73
69
  def nest(delegate: false, &block)
74
- yield @initialization if block
75
-
76
- @assembler.inject(
77
- @abstract_factory.build_order_list.reverse,
78
- @initialization.to_h,
79
- callbacks: callbacks,
80
- delegate: delegate
81
- )
70
+ yield @assembler.initialization if block
71
+
72
+ @assembler.inject(@abstract_factory.build_order_list.reverse, delegate: delegate)
82
73
  end
83
74
 
84
75
  def subclass(&def_block)
@@ -87,8 +78,13 @@ module Nina
87
78
  @abstract_factory = Class.new(abstract_factory)
88
79
  @abstract_factory.class_eval(&def_block)
89
80
  @abstract_factory.build_order_list.freeze
90
- @initialization = Initialization.new(@abstract_factory.factories.keys)
91
- @assembler = Assembler.new(@abstract_factory)
81
+ @assembler = Assembler.new(@abstract_factory, @assembler.callbacks)
82
+ end
83
+
84
+ def update(name, object)
85
+ @observers.each do |observer|
86
+ observer.public_send(:"on_#{name}_created", object) if observer.respond_to?(:"on_#{name}_created")
87
+ end
92
88
  end
93
89
  end
94
90
  end
data/lib/nina/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nina
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.5'
5
5
  end
data/lib/nina.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'toritori'
4
+ require 'observer'
4
5
  require 'nina/assembler'
5
6
  require 'nina/builder'
6
7
 
@@ -31,7 +32,45 @@ module Nina
31
32
  end
32
33
  end
33
34
 
35
+ # Adds ability to delegeate methods via method_missing
36
+ module MethodMissingDelegation
37
+ def method_missing(name, *attrs, **kwargs, &block)
38
+ if (prev = predecessors.lazy.detect { |o| o.public_methods.include?(name) })
39
+ prev.public_send(name, *attrs, **kwargs, &block)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def respond_to_missing?(method_name, _include_private = false)
46
+ public_methods.detect { |m| m == :predecessor } || super
47
+ end
48
+
49
+ def predecessors
50
+ Enumerator.new do |y|
51
+ obj = self
52
+ y << obj = obj.predecessor while obj.methods.detect { |m| m == :predecessor }
53
+ end
54
+ end
55
+ end
56
+
34
57
  def self.included(receiver)
35
58
  receiver.extend ClassMethods
36
59
  end
60
+
61
+ def self.def_accessor(accessor, on:, to:, delegate: false)
62
+ on.define_singleton_method(accessor) { to }
63
+ on.define_singleton_method(:predecessor) { to }
64
+ return unless delegate
65
+
66
+ on.extend(MethodMissingDelegation)
67
+ end
68
+
69
+ def self.linked_list(build_config, delegate: false)
70
+ build_order = build_config.keys
71
+ build_config.each.with_index(-1).inject(nil) do |prev, ((_, object), idx)|
72
+ Nina.def_accessor(build_order[idx], on: object, to: prev, delegate: delegate) if prev
73
+ object
74
+ end
75
+ end
37
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nina
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.5
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-07-12 00:00:00.000000000 Z
11
+ date: 2024-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toritori
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: 0.2.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: 0.2.1
27
27
  description: Reduce biolerplate code when you need to create complex OOD composition
28
28
  email:
29
29
  - andriy.baran.v@gmail.com