n1_loader 1.7.0 → 1.7.2

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: e9be9c5e7d5e551d253a327cd3d130a38821ef49a43cab60235cc5363a4093d0
4
- data.tar.gz: 55c8e748bf52fc05b8648d81d907963b4a60eae0b7aa680d0c491987b43303d3
3
+ metadata.gz: 61980f2b94429810da38a914db9e3779385a86cf0fbe95773311b19a2551c5a3
4
+ data.tar.gz: 8817ef5434d16ba5eb13deec0a78110fae07b9def1256e6b1d163deb02ed5a05
5
5
  SHA512:
6
- metadata.gz: b626c836856198a9e0d0f54daedd0299b2cd7eb0648ddde369a6b7f923751b31d402c8ba03ab67bb064b884e5c5f035babcd1f59d0bef93db26968f7e6fca7ae
7
- data.tar.gz: 640e8decd4c53e4f09451041392b964b5f0e59a273719673978e4bf62d26543364b5b4166d97833b7a5084ebacfe7921a921a5c0aae3938c3ce9394f6627bfc8
6
+ metadata.gz: b78afcfdc23c584456a3e5daef5c8f18f102bafffffbb06640275afdd9ee2e65368384d29d2dd77f0a5c991a4c281d808086bc1648da38a304eac743b3265fcd
7
+ data.tar.gz: 26795d6614b90f868a6aaec760180e0270a4726c5ce0e1f88fc04b97cfc751a8627a8d94efc27d2443d82cc145207759b595afe3383a4f8a38cacc8af75d4b3f
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- ## [1.6.7] - 2023/07/30
1
+ ## [1.7.2] - 2023/08/04
2
+
3
+ - Refactor core that ended up with speed boost.
4
+
5
+ ## [1.7.1] - 2023/07/30
6
+
7
+ - Fix interface discrepancy for `N1LoaderReflection`. Thanks [Denis Talakevich](https://github.com/senid231) for suggesting it!
8
+
9
+ ## [1.7.0] - 2023/07/30
2
10
 
3
11
  Extend the flexibility of loading data comparison. Thanks [Nazar Matus](https://github.com/FunkyloverOne) for suggesting it!
4
12
 
@@ -4,7 +4,7 @@ module N1Loader
4
4
  module ActiveRecord
5
5
  module Associations
6
6
  module Preloader # :nodoc:
7
- N1LoaderReflection = Struct.new(:key, :loader) do
7
+ N1LoaderReflection = Struct.new(:name, :loader) do
8
8
  def options
9
9
  {}
10
10
  end
@@ -12,7 +12,7 @@ module N1Loader
12
12
 
13
13
  def preloaders_for_one(association, records, scope)
14
14
  grouped_records(association, records).flat_map do |reflection, klasses|
15
- next N1Loader::Preloader.new(records).preload(reflection.key) if reflection.is_a?(N1LoaderReflection)
15
+ next N1Loader::Preloader.new(records).preload(reflection.name) if reflection.is_a?(N1LoaderReflection)
16
16
 
17
17
  klasses.map do |rhs_klass, rs|
18
18
  loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope)
@@ -24,11 +24,11 @@ module N1Loader
24
24
 
25
25
  def grouped_records(association, records)
26
26
  n1_load_records, records = records.partition do |record|
27
- record.class.respond_to?(:n1_loader_defined?) && record.class.n1_loader_defined?(association)
27
+ record.class.respond_to?(:n1_loaders) && record.class.n1_loaders.key?(association)
28
28
  end
29
29
 
30
30
  hash = n1_load_records.group_by do |record|
31
- N1LoaderReflection.new(association, record.class.n1_loader(association))
31
+ N1LoaderReflection.new(association, record.class.n1_loaders[association])
32
32
  end
33
33
 
34
34
  hash.merge(super)
@@ -4,7 +4,7 @@ module N1Loader
4
4
  module ActiveRecord
5
5
  module Associations
6
6
  module Preloader # :nodoc:
7
- N1LoaderReflection = Struct.new(:key, :loader) do
7
+ N1LoaderReflection = Struct.new(:name, :loader) do
8
8
  def options
9
9
  {}
10
10
  end
@@ -13,16 +13,16 @@ module N1Loader
13
13
  def preloaders_for_reflection(reflection, records, scope)
14
14
  return super unless reflection.is_a?(N1LoaderReflection)
15
15
 
16
- N1Loader::Preloader.new(records).preload(reflection.key)
16
+ N1Loader::Preloader.new(records).preload(reflection.name)
17
17
  end
18
18
 
19
19
  def grouped_records(association, records, polymorphic_parent)
20
20
  n1_load_records, records = records.partition do |record|
21
- record.class.respond_to?(:n1_loader_defined?) && record.class.n1_loader_defined?(association)
21
+ record.class.respond_to?(:n1_loaders) && record.class.n1_loaders[association]
22
22
  end
23
23
 
24
24
  hash = n1_load_records.group_by do |record|
25
- N1LoaderReflection.new(association, record.class.n1_loader(association))
25
+ N1LoaderReflection.new(association, record.class.n1_loaders[association])
26
26
  end
27
27
 
28
28
  hash.merge(super)
@@ -4,7 +4,7 @@ module N1Loader
4
4
  module ActiveRecord
5
5
  module Associations
6
6
  module Preloader # :nodoc:
7
- N1LoaderReflection = Struct.new(:key, :loader) do
7
+ N1LoaderReflection = Struct.new(:name, :loader) do
8
8
  def options
9
9
  {}
10
10
  end
@@ -13,16 +13,16 @@ module N1Loader
13
13
  def preloaders_for_reflection(reflection, records)
14
14
  return super unless reflection.is_a?(N1LoaderReflection)
15
15
 
16
- N1Loader::Preloader.new(records).preload(reflection.key)
16
+ N1Loader::Preloader.new(records).preload(reflection.name)
17
17
  end
18
18
 
19
19
  def grouped_records # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
20
20
  n1_load_records, records = source_records.partition do |record|
21
- record.class.respond_to?(:n1_loader_defined?) && record.class.n1_loader_defined?(association)
21
+ record.class.respond_to?(:n1_loaders) && record.class.n1_loaders[association]
22
22
  end
23
23
 
24
24
  h = n1_load_records.group_by do |record|
25
- N1LoaderReflection.new(association, record.class.n1_loader(association))
25
+ N1LoaderReflection.new(association, record.class.n1_loaders[association])
26
26
  end
27
27
 
28
28
  polymorphic_parent = !root? && parent.polymorphic?
@@ -2,22 +2,13 @@
2
2
 
3
3
  module N1Loader
4
4
  module ArLazyPreload
5
- module Loadable
6
- module ClassMethods # :nodoc:
7
- def n1_optimized(name, loader = nil, &block)
8
- name, loader_name, loader_variable_name = super
5
+ module Loadable # :nodoc:
6
+ def n1_loader(name)
7
+ return n1_loaders[name] if n1_loaders[name]
9
8
 
10
- define_method(loader_name) do
11
- loader = instance_variable_get(loader_variable_name)
12
- return loader if loader
9
+ ContextAdapter.new(lazy_preload_context).try_preload_lazily(name) if respond_to?(:lazy_preload_context)
13
10
 
14
- if respond_to?(:lazy_preload_context) && ContextAdapter.new(lazy_preload_context).try_preload_lazily(name)
15
- return instance_variable_get(loader_variable_name)
16
- end
17
-
18
- send("#{loader_name}_reload")
19
- end
20
- end
11
+ super
21
12
  end
22
13
  end
23
14
  end
@@ -17,7 +17,7 @@ require_relative "ar_lazy_preload/loader_patch"
17
17
  require_relative "ar_lazy_preload/loader"
18
18
  require_relative "ar_lazy_preload/context"
19
19
 
20
- N1Loader::Loadable::ClassMethods.prepend(N1Loader::ArLazyPreload::Loadable::ClassMethods)
20
+ N1Loader::Loadable.prepend(N1Loader::ArLazyPreload::Loadable)
21
21
  N1Loader::Preloader.prepend(N1Loader::ArLazyPreload::PreloaderPatch)
22
22
  N1Loader::Loader.prepend(N1Loader::ArLazyPreload::LoaderPatch)
23
23
  N1Loader::LoaderCollection.prepend(N1Loader::ArLazyPreload::LoaderCollectionPatch)
@@ -7,14 +7,14 @@ module N1Loader
7
7
  # include N1Loader::Loadable
8
8
  #
9
9
  # # with inline loader
10
- # n1_loader :something do
10
+ # n1_optimized :something do
11
11
  # def perform(elements)
12
12
  # elements.each { |element| fulfill(element, element.calculate_something) }
13
13
  # end
14
14
  # end
15
15
  #
16
16
  # # with custom loader
17
- # n1_loader :something, MyLoader
17
+ # n1_optimized :something, MyLoader
18
18
  # end
19
19
  #
20
20
  # # custom loader
@@ -24,23 +24,21 @@ module N1Loader
24
24
  # end
25
25
  # end
26
26
  module Loadable
27
- include Name
27
+ def n1_loaders
28
+ @n1_loaders ||= {}
29
+ end
28
30
 
29
31
  def n1_loader(name)
30
- name = n1_loader_name(name)
31
-
32
- send("#{name}_loader")
32
+ n1_loaders[name]
33
33
  end
34
34
 
35
- def n1_loader_set(name, loader_collection)
36
- name = n1_loader_name(name)
37
-
38
- send("#{name}_loader=", loader_collection)
35
+ def n1_loader_reload(name)
36
+ n1_loaders[name] = LoaderCollection.new(self.class.n1_loaders[name], [self])
39
37
  end
40
38
 
41
39
  def n1_clear_cache
42
- self.class.n1_loaders.each do |name|
43
- n1_loader_set(name, nil)
40
+ self.class.n1_loaders.each_key do |name|
41
+ n1_loaders[name] = nil
44
42
  end
45
43
  end
46
44
 
@@ -49,61 +47,20 @@ module N1Loader
49
47
  end
50
48
 
51
49
  module ClassMethods # :nodoc:
52
- include Name
53
-
54
- def n1_loader(name)
55
- name = n1_loader_name(name)
56
-
57
- send("#{name}_loader")
58
- end
59
-
60
- def n1_loader_defined?(name)
61
- name = n1_loader_name(name)
62
-
63
- respond_to?("#{name}_loader")
64
- end
65
-
66
50
  def n1_loaders
67
- @n1_loaders ||= superclass.respond_to?(:n1_loaders) ? superclass.n1_loaders.dup : []
51
+ @n1_loaders ||= superclass.respond_to?(:n1_loaders) ? superclass.n1_loaders.dup : {}
68
52
  end
69
53
 
70
- def n1_optimized(name, loader = nil, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
71
- loader ||= Class.new(N1Loader::Loader) do
72
- if block.arity == 1
73
- define_method(:perform, &block)
74
- else
75
- class_eval(&block)
76
- end
77
- end
78
- loader_name = "#{n1_loader_name(name)}_loader"
79
- loader_variable_name = "@#{loader_name}"
80
-
81
- n1_loaders << name
82
-
83
- define_singleton_method(loader_name) do
84
- loader
85
- end
86
-
87
- define_method("#{loader_name}_reload") do
88
- instance_variable_set(loader_variable_name,
89
- N1Loader::LoaderCollection.new(self.class.send(loader_name), [self]))
90
- end
54
+ def n1_optimized(name, loader = nil, &block)
55
+ loader ||= LoaderBuilder.build(&block)
91
56
 
92
- define_method("#{loader_name}=") do |loader_collection_instance|
93
- instance_variable_set(loader_variable_name, loader_collection_instance)
94
- end
95
-
96
- define_method(loader_name) do
97
- instance_variable_get(loader_variable_name) || send("#{loader_name}_reload")
98
- end
57
+ n1_loaders[name] = loader
99
58
 
100
59
  define_method(name) do |reload: false, **args|
101
- send("#{loader_name}_reload") if reload
60
+ n1_loader_reload(name) if reload || n1_loader(name).nil?
102
61
 
103
- send(loader_name).with(**args).for(self)
62
+ n1_loader(name).with(**args).for(self)
104
63
  end
105
-
106
- [name, loader_name, loader_variable_name]
107
64
  end
108
65
  end
109
66
  end
@@ -62,11 +62,10 @@ module N1Loader
62
62
 
63
63
  attr_reader :elements, :args
64
64
 
65
- def check_missing_arguments! # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
65
+ def check_missing_arguments!
66
66
  return unless (arguments = self.class.arguments)
67
67
 
68
- required_arguments = arguments.reject { |argument| argument[:optional] }
69
- .map { |argument| argument[:name] }
68
+ required_arguments = required_arguments(arguments)
70
69
 
71
70
  return if required_arguments.all? { |argument| args.key?(argument) }
72
71
 
@@ -74,8 +73,12 @@ module N1Loader
74
73
 
75
74
  list = missing_arguments.map { |argument| ":#{argument}" }.join(", ")
76
75
 
77
- raise MissingArgument,
78
- "Loader requires [#{list}] arguments but they are missing"
76
+ raise MissingArgument, "Loader requires [#{list}] arguments but they are missing"
77
+ end
78
+
79
+ def required_arguments(args)
80
+ args.reject { |argument| argument[:optional] }
81
+ .map { |argument| argument[:name] }
79
82
  end
80
83
 
81
84
  def check_arguments!
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module N1Loader
4
+ # The class builds {N1Loader::Loader}
5
+ class LoaderBuilder
6
+ def self.build(&block)
7
+ Class.new(N1Loader::Loader) do
8
+ if block.arity == 1
9
+ define_method(:perform, &block)
10
+ else
11
+ class_eval(&block)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -18,22 +18,19 @@ module N1Loader
18
18
  keys.flatten(1).flat_map do |key|
19
19
  elements
20
20
  .group_by { |element| loader_class(element, key) }
21
- .map do |loader_class, grouped_elements|
22
- next unless loader_class
23
-
21
+ .select { |loader_class, _| loader_class }
22
+ .map do |(loader_class, grouped_elements)|
24
23
  loader_collection = N1Loader::LoaderCollection.new(loader_class, grouped_elements)
25
- grouped_elements.each { |grouped_element| grouped_element.n1_loader_set(key, loader_collection) }
24
+ grouped_elements.each { |grouped_element| grouped_element.n1_loaders[key] = loader_collection }
26
25
  loader_collection
27
- end.compact
26
+ end
28
27
  end
29
28
  end
30
29
 
31
30
  private
32
31
 
33
32
  def loader_class(element, key)
34
- element.class.respond_to?(:n1_loader_defined?) &&
35
- element.class.n1_loader_defined?(key) &&
36
- element.class.n1_loader(key)
33
+ element.class.respond_to?(:n1_loaders) && element.class.n1_loaders[key]
37
34
  end
38
35
  end
39
36
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module N1Loader
4
- VERSION = "1.7.0"
4
+ VERSION = "1.7.2"
5
5
  end
data/lib/n1_loader.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative "n1_loader/version"
4
4
 
5
- require_relative "n1_loader/core/name"
5
+ require_relative "n1_loader/core/loader_builder"
6
6
  require_relative "n1_loader/core/loader"
7
7
  require_relative "n1_loader/core/loader_collection"
8
8
  require_relative "n1_loader/core/loadable"
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: 1.7.0
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeniy Demin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-30 00:00:00.000000000 Z
11
+ date: 2023-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -195,8 +195,8 @@ files:
195
195
  - lib/n1_loader/ar_lazy_preload/preloader_patch.rb
196
196
  - lib/n1_loader/core/loadable.rb
197
197
  - lib/n1_loader/core/loader.rb
198
+ - lib/n1_loader/core/loader_builder.rb
198
199
  - lib/n1_loader/core/loader_collection.rb
199
- - lib/n1_loader/core/name.rb
200
200
  - lib/n1_loader/core/preloader.rb
201
201
  - lib/n1_loader/version.rb
202
202
  - n1_loader.gemspec
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module N1Loader
4
- # Add support of question mark names
5
- module Name
6
- def n1_loader_name(name)
7
- to_sym = name.is_a?(Symbol)
8
-
9
- converted = name.to_s.gsub("?", "_question_mark")
10
-
11
- to_sym ? converted.to_sym : converted
12
- end
13
- end
14
- end