n1_loader 2.2.0 → 3.0.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/lib/n1_loader/active_record/loader.rb +1 -1
- data/lib/n1_loader/ar_lazy_preload/loader_patch.rb +11 -6
- data/lib/n1_loader/core/loadable.rb +12 -0
- data/lib/n1_loader/core/loader.rb +18 -16
- data/lib/n1_loader/goldiloader/context.rb +7 -0
- data/lib/n1_loader/goldiloader/context_adapter.rb +30 -0
- data/lib/n1_loader/goldiloader/loadable.rb +15 -0
- data/lib/n1_loader/goldiloader/loader.rb +28 -0
- data/lib/n1_loader/goldiloader/loader_collection_patch.rb +18 -0
- data/lib/n1_loader/goldiloader/loader_patch.rb +28 -0
- data/lib/n1_loader/goldiloader/preloader_patch.rb +23 -0
- data/lib/n1_loader/goldiloader.rb +21 -0
- data/lib/n1_loader/version.rb +1 -1
- data/lib/n1_loader.rb +1 -0
- metadata +24 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 993f807b671a08f82ed5ad7eff20cae7ab4d8e910772ba944543f8a46343c313
|
|
4
|
+
data.tar.gz: d0489f877243e19caf4c5b8fab6083dbe283aad6e89199386d611745840065ce
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f47c6eb0400062948a5bb9c19cbb71b56cc10615773f5dd031fcc138485303ddbd3bb9b9f0070afc5f5baaaebd917c8da0f2c00dd93a29956bcdfca9d6581a73
|
|
7
|
+
data.tar.gz: 7cbcf9de6b8b20b0e2d100d79f787343f542200da3ec234d0f13ef6353ca0bbf3e05afd06584528d70701ff08bfd461d63c9c83625164f9579123417a092a406
|
|
@@ -6,17 +6,22 @@ module N1Loader
|
|
|
6
6
|
module LoaderPatch
|
|
7
7
|
attr_accessor :context_setup
|
|
8
8
|
|
|
9
|
-
def loaded
|
|
10
|
-
return
|
|
9
|
+
def loaded?
|
|
10
|
+
return true if @already_loaded && @already_context
|
|
11
11
|
|
|
12
12
|
super
|
|
13
13
|
|
|
14
|
-
synchronize
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
synchronize { non_thread_safe_context_setting unless @already_context }
|
|
15
|
+
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def non_thread_safe_context_setting
|
|
20
|
+
return if @already_context
|
|
21
|
+
|
|
22
|
+
context_setup&.call(loaded_by_identity.values.flatten)
|
|
17
23
|
|
|
18
24
|
@already_context = true
|
|
19
|
-
@loaded_by_identity
|
|
20
25
|
end
|
|
21
26
|
end
|
|
22
27
|
end
|
|
@@ -33,9 +33,21 @@ module N1Loader
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def n1_bind_to(collection)
|
|
36
|
+
unless collection.is_a?(Array) && collection.any? do |obj|
|
|
37
|
+
obj == self || obj.equal?(self)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
raise InvalidBinding,
|
|
41
|
+
"assigned collection should be array and include object"
|
|
42
|
+
end
|
|
43
|
+
|
|
36
44
|
@n1_binding = collection
|
|
37
45
|
end
|
|
38
46
|
|
|
47
|
+
def n1_bind_to?
|
|
48
|
+
!@n1_binding.nil?
|
|
49
|
+
end
|
|
50
|
+
|
|
39
51
|
def n1_loader_reload(name)
|
|
40
52
|
elements = @n1_binding || [self]
|
|
41
53
|
collection = LoaderCollection.new(self.class.n1_loaders[name], elements)
|
|
@@ -47,14 +47,14 @@ module N1Loader
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def for(element)
|
|
50
|
-
|
|
50
|
+
return unless loaded?
|
|
51
51
|
|
|
52
|
-
if
|
|
52
|
+
if loaded_by_identity.empty? && elements.any?
|
|
53
53
|
raise NotFilled, "Nothing was preloaded, perhaps you forgot to use fulfill method"
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
return
|
|
57
|
-
return
|
|
56
|
+
return loaded_by_identity[element] if loaded_by_identity.key?(element)
|
|
57
|
+
return loaded_by_value[element] if loaded_by_value.key?(element)
|
|
58
58
|
|
|
59
59
|
raise NotLoaded, "The data was not preloaded for the given element"
|
|
60
60
|
end
|
|
@@ -66,7 +66,7 @@ module N1Loader
|
|
|
66
66
|
|
|
67
67
|
private
|
|
68
68
|
|
|
69
|
-
attr_reader :elements, :args
|
|
69
|
+
attr_reader :elements, :args, :loaded_by_value, :loaded_by_identity
|
|
70
70
|
|
|
71
71
|
def check_missing_arguments!
|
|
72
72
|
return unless (arguments = self.class.arguments)
|
|
@@ -107,22 +107,19 @@ module N1Loader
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def fulfill(element, value)
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
loaded_by_identity[element] = value
|
|
111
|
+
loaded_by_value[element] = value
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
def
|
|
115
|
-
return if @already_loaded
|
|
114
|
+
def loaded?
|
|
115
|
+
return true if @already_loaded
|
|
116
116
|
|
|
117
|
-
synchronize {
|
|
118
|
-
end
|
|
117
|
+
synchronize { non_thread_safe_loading unless @already_loaded }
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
ensure_loaded
|
|
122
|
-
@loaded_by_identity
|
|
119
|
+
true
|
|
123
120
|
end
|
|
124
121
|
|
|
125
|
-
def
|
|
122
|
+
def non_thread_safe_loading # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
126
123
|
return if @already_loaded
|
|
127
124
|
|
|
128
125
|
check_arguments!
|
|
@@ -133,8 +130,13 @@ module N1Loader
|
|
|
133
130
|
if respond_to?(:single) && elements.size == 1
|
|
134
131
|
fulfill(elements.first, single(elements.first))
|
|
135
132
|
elsif elements.any?
|
|
136
|
-
elements.each { |el| el.n1_bind_to(elements) if el.respond_to?(:n1_bind_to) }
|
|
137
133
|
perform(elements)
|
|
134
|
+
|
|
135
|
+
# propagate context to loaded objects only when it was set
|
|
136
|
+
if elements.first.respond_to?(:n1_bind_to?) && elements.first.n1_bind_to?
|
|
137
|
+
loaded_objects = loaded_by_identity.values.flatten
|
|
138
|
+
loaded_objects.each { |el| el.n1_bind_to(loaded_objects) if el.respond_to?(:n1_bind_to) }
|
|
139
|
+
end
|
|
138
140
|
end
|
|
139
141
|
|
|
140
142
|
@already_loaded = true
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Returns cached N1Loader::LoaderCollection from context for a loader.
|
|
4
|
+
# In case there is none yet, saves passed block to a cache.
|
|
5
|
+
Goldiloader::AutoIncludeContext.define_method :fetch_n1_loader_collection do |loader, &block|
|
|
6
|
+
(@n1_loader_collections ||= {})[loader] ||= block.call
|
|
7
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module N1Loader
|
|
4
|
+
module Goldiloader
|
|
5
|
+
# Context adapter for injected N1Loader loaders.
|
|
6
|
+
class ContextAdapter
|
|
7
|
+
attr_reader :context
|
|
8
|
+
|
|
9
|
+
def initialize(context)
|
|
10
|
+
@context = context
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Trigger preloading for +association_name+ across all models in the context.
|
|
14
|
+
def try_preload_lazily(association_name)
|
|
15
|
+
perform_preloading(association_name) if context
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Initialize preloader for +association_name+ with context builder callback.
|
|
19
|
+
# The callback will be executed when records are loaded.
|
|
20
|
+
def perform_preloading(association_name)
|
|
21
|
+
context_setup = lambda { |records|
|
|
22
|
+
ar_records = records.flatten(1).select { |record| record.respond_to?(:auto_include_context=) }
|
|
23
|
+
::Goldiloader::AutoIncludeContext.register_models(ar_records) unless ar_records.empty?
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
N1Loader::Preloader.new(context.models, context_setup).preload(association_name)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module N1Loader
|
|
4
|
+
module Goldiloader
|
|
5
|
+
module Loadable # :nodoc:
|
|
6
|
+
def n1_loader(name)
|
|
7
|
+
return n1_loaders[name] if n1_loaders[name]
|
|
8
|
+
|
|
9
|
+
ContextAdapter.new(auto_include_context).try_preload_lazily(name) if respond_to?(:auto_include_context)
|
|
10
|
+
|
|
11
|
+
super
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Raised when a single object without Goldiloader context support was passed to an isolated loader.
|
|
4
|
+
N1Loader::Loader::UnsupportedGoldiloader = Class.new(StandardError)
|
|
5
|
+
|
|
6
|
+
# Defines a singleton method that allows isolated loaders
|
|
7
|
+
# to use Goldiloader context without passing sibling records.
|
|
8
|
+
N1Loader::Loader.define_singleton_method(:for) do |element, **args|
|
|
9
|
+
# It is required to have a Goldiloader context supported
|
|
10
|
+
raise N1Loader::Loader::UnsupportedGoldiloader unless element.respond_to?(:auto_include_context)
|
|
11
|
+
|
|
12
|
+
context = element.auto_include_context
|
|
13
|
+
|
|
14
|
+
# Fetch or initialize loader from Goldiloader context
|
|
15
|
+
loader_collection = context.fetch_n1_loader_collection(self) do
|
|
16
|
+
context_setup = lambda { |records|
|
|
17
|
+
ar_records = records.flatten(1).select { |record| record.respond_to?(:auto_include_context=) }
|
|
18
|
+
::Goldiloader::AutoIncludeContext.register_models(ar_records) unless ar_records.empty?
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
N1Loader::LoaderCollection.new(self, context.models).tap do |collection|
|
|
22
|
+
collection.context_setup = context_setup
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Fetch value from loader
|
|
27
|
+
loader_collection.with(**args).for(element)
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module N1Loader
|
|
4
|
+
module Goldiloader
|
|
5
|
+
# A patch to {N1Loader::LoaderCollection} to setup lazy context lazily.
|
|
6
|
+
module LoaderCollectionPatch
|
|
7
|
+
attr_accessor :context_setup
|
|
8
|
+
|
|
9
|
+
def with(**args)
|
|
10
|
+
result = super
|
|
11
|
+
|
|
12
|
+
result.context_setup = context_setup if context_setup && result.context_setup.nil?
|
|
13
|
+
|
|
14
|
+
result
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module N1Loader
|
|
4
|
+
module Goldiloader
|
|
5
|
+
# A patch to {N1Loader::Loader} to setup lazy context lazily.
|
|
6
|
+
module LoaderPatch
|
|
7
|
+
attr_accessor :context_setup
|
|
8
|
+
|
|
9
|
+
def loaded?
|
|
10
|
+
return true if @already_loaded && @already_context
|
|
11
|
+
|
|
12
|
+
super
|
|
13
|
+
|
|
14
|
+
synchronize { non_thread_safe_context_setting unless @already_context }
|
|
15
|
+
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def non_thread_safe_context_setting
|
|
20
|
+
return if @already_context
|
|
21
|
+
|
|
22
|
+
context_setup&.call(loaded_by_identity.values.flatten)
|
|
23
|
+
|
|
24
|
+
@already_context = true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module N1Loader
|
|
4
|
+
module Goldiloader
|
|
5
|
+
# A patch to {N1Loader::Preloader} to setup lazy context lazily.
|
|
6
|
+
module PreloaderPatch
|
|
7
|
+
def initialize(elements, context_setup = nil)
|
|
8
|
+
super(elements)
|
|
9
|
+
@context_setup = context_setup
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def preload(*keys)
|
|
13
|
+
super.each do |loader_collection|
|
|
14
|
+
loader_collection.context_setup = context_setup
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
attr_reader :context_setup
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Load core library
|
|
4
|
+
require_relative "active_record"
|
|
5
|
+
|
|
6
|
+
# Load integration dependency
|
|
7
|
+
require "goldiloader"
|
|
8
|
+
|
|
9
|
+
# Library integration
|
|
10
|
+
require_relative "goldiloader/loadable"
|
|
11
|
+
require_relative "goldiloader/context_adapter"
|
|
12
|
+
require_relative "goldiloader/loader_collection_patch"
|
|
13
|
+
require_relative "goldiloader/preloader_patch"
|
|
14
|
+
require_relative "goldiloader/loader_patch"
|
|
15
|
+
require_relative "goldiloader/loader"
|
|
16
|
+
require_relative "goldiloader/context"
|
|
17
|
+
|
|
18
|
+
N1Loader::Loadable.prepend(N1Loader::Goldiloader::Loadable)
|
|
19
|
+
N1Loader::Preloader.prepend(N1Loader::Goldiloader::PreloaderPatch)
|
|
20
|
+
N1Loader::Loader.prepend(N1Loader::Goldiloader::LoaderPatch)
|
|
21
|
+
N1Loader::LoaderCollection.prepend(N1Loader::Goldiloader::LoaderCollectionPatch)
|
data/lib/n1_loader/version.rb
CHANGED
data/lib/n1_loader.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: n1_loader
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evgeniy Demin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: mutex_m
|
|
@@ -66,6 +66,20 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0.11'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: goldiloader
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '3'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3'
|
|
69
83
|
- !ruby/object:Gem::Dependency
|
|
70
84
|
name: graphql
|
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -179,6 +193,14 @@ files:
|
|
|
179
193
|
- lib/n1_loader/core/loader_builder.rb
|
|
180
194
|
- lib/n1_loader/core/loader_collection.rb
|
|
181
195
|
- lib/n1_loader/core/preloader.rb
|
|
196
|
+
- lib/n1_loader/goldiloader.rb
|
|
197
|
+
- lib/n1_loader/goldiloader/context.rb
|
|
198
|
+
- lib/n1_loader/goldiloader/context_adapter.rb
|
|
199
|
+
- lib/n1_loader/goldiloader/loadable.rb
|
|
200
|
+
- lib/n1_loader/goldiloader/loader.rb
|
|
201
|
+
- lib/n1_loader/goldiloader/loader_collection_patch.rb
|
|
202
|
+
- lib/n1_loader/goldiloader/loader_patch.rb
|
|
203
|
+
- lib/n1_loader/goldiloader/preloader_patch.rb
|
|
182
204
|
- lib/n1_loader/version.rb
|
|
183
205
|
homepage: https://github.com/djezzzl/n1_loader
|
|
184
206
|
licenses:
|