n1_loader 1.2.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b9b61121f94d9dba30e969c1b9a3fa9c812292d618434a98262c90aef43e6cd
4
- data.tar.gz: a1ecf5359a1a53200e354b30289566a437cf372c54ccf3f13c2e0adc2cb71640
3
+ metadata.gz: cc47894a27d425f70a38dc43b9b40053d823f4815fe8e135a7cb1cf5afbde0f3
4
+ data.tar.gz: 132d5851c19763db2f1910ebeeb6a368437aba6d3340c2c69ad2ffe348791011
5
5
  SHA512:
6
- metadata.gz: 5c545cc2033dc8e75edddd5c948eed78fc1d965464522147841d30e3c6a02aebb0b6758d3f801b020c25d62618f7ae4bbb7ff11441748f798546351b1bf34d85
7
- data.tar.gz: a60fa813399debf1ae9c8f839272a683c2a7f733ea392b4b1bd4169af55369a1d3be2fd8648a548e50093005e3d2df962437adf08f1f9fdf1338fa4ab6217df7
6
+ metadata.gz: 945258069b57bc7cd0fe26416411322886d734db0ed4eead1c88a3acced70bdb14ffc92eb9403e5d346c0853d64dc09e5afb8039a9026c9b4c09a1cc6f5fc9e8
7
+ data.tar.gz: 036e5a8a4b2d63bed2aee558164fdd042ac8c0c68b0ecdb1d5ec9f64231ca9f6841dc56cd6cdc63b87fdb9bf964e4f42089f89d9783cf2513cf81243a473150a
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
- ## [1.2.0]
1
+ ## [1.3.0] - 2022-02-22
2
+
3
+ - add support of named arguments with `argument <name>`
4
+
5
+ BREAKING CHANGES:
6
+ - rename `n1_load` to `n1_optimized`
7
+ - rework `def self.arguments_key` to `cache_key`
8
+
9
+ ## [1.2.0] - 2022-01-14
2
10
 
3
11
  - Introduce arguments support.
4
12
 
data/README.md CHANGED
@@ -45,7 +45,7 @@ class User
45
45
  include N1Loader::Loadable
46
46
 
47
47
  # with inline loader
48
- n1_loader :orders_count do |users|
48
+ n1_optimized :orders_count do |users|
49
49
  orders_per_user = Order.where(user: users).group(:user_id).count
50
50
 
51
51
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -69,7 +69,7 @@ class User
69
69
  include N1Loader::Loadable
70
70
 
71
71
  # with inline loader
72
- n1_loader :orders_count do |users|
72
+ n1_optimized :orders_count do |users|
73
73
  orders_per_user = Order.where(user: users).group(:user_id).count
74
74
 
75
75
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -98,14 +98,14 @@ end
98
98
 
99
99
  class User
100
100
  include N1Loader::Loadable
101
-
102
- n1_loader :orders_count, OrdersCountLoader
101
+
102
+ n1_optimized :orders_count, OrdersCountLoader
103
103
  end
104
104
 
105
105
  class Customer
106
106
  include N1Loader::Loadable
107
-
108
- n1_loader :orders_count, OrdersCountLoader
107
+
108
+ n1_optimized :orders_count, OrdersCountLoader
109
109
  end
110
110
 
111
111
  User.new.orders_count # => works
@@ -119,7 +119,7 @@ class User
119
119
  include N1Loader::Loadable
120
120
 
121
121
  # with inline loader
122
- n1_loader :orders_count do |users|
122
+ n1_optimized :orders_count do |users|
123
123
  orders_per_user = Order.where(user: users).group(:user_id).count
124
124
 
125
125
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -159,8 +159,8 @@ end
159
159
  ```ruby
160
160
  class User
161
161
  include N1Loader::Loadable
162
-
163
- n1_loader :orders_count do # no arguments passed to the block, so we can override both perform and single.
162
+
163
+ n1_optimized :orders_count do # no arguments passed to the block, so we can override both perform and single.
164
164
  def perform(users)
165
165
  orders_per_user = Order.where(user: users).group(:user_id).count
166
166
 
@@ -188,7 +188,7 @@ users.map(&:orders_count) # perform will be used once without N+1
188
188
  class User
189
189
  include N1Loader::Loadable
190
190
 
191
- n1_loader :orders_count do |users, type|
191
+ n1_optimized :orders_count do |users, type|
192
192
  orders_per_user = Order.where(type: type, user: users).group(:user_id).count
193
193
 
194
194
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -212,16 +212,16 @@ you may want to override it, for example:
212
212
  class User
213
213
  include N1Loader::Loadable
214
214
 
215
- n1_loader :orders_count do
215
+ n1_optimized :orders_count do
216
+ argument :sale
217
+
218
+ cache_key { sale.id }
219
+
216
220
  def perform(users, sale)
217
221
  orders_per_user = Order.where(sale: sale, user: users).group(:user_id).count
218
222
 
219
223
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
220
224
  end
221
-
222
- def self.arguments_key(sale)
223
- sale.id
224
- end
225
225
  end
226
226
  end
227
227
 
@@ -235,11 +235,13 @@ user.orders_count(Sale.first) # the cached value will be returned
235
235
 
236
236
  ### [ActiveRecord][5]
237
237
 
238
+ _Note_: Rails 7 support is coming soon! Stay tuned!
239
+
238
240
  ```ruby
239
241
  class User < ActiveRecord::Base
240
242
  include N1Loader::Loadable
241
-
242
- n1_loader :orders_count do |users|
243
+
244
+ n1_optimized :orders_count do |users|
243
245
  orders_per_user = Order.where(user: users).group(:user_id).count
244
246
 
245
247
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -266,8 +268,8 @@ users.map(&:orders_count)
266
268
  ```ruby
267
269
  class User < ActiveRecord::Base
268
270
  include N1Loader::Loadable
269
-
270
- n1_loader :orders_count do |users|
271
+
272
+ n1_optimized :orders_count do |users|
271
273
  orders_per_user = Order.where(user: users).group(:user_id).count
272
274
 
273
275
  users.each { |user| fulfill(user, orders_per_user[user.id]) }
@@ -4,7 +4,7 @@ module N1Loader
4
4
  module ArLazyPreload
5
5
  module Loadable
6
6
  module ClassMethods # :nodoc:
7
- def n1_load(name, loader = nil, &block)
7
+ def n1_optimized(name, loader = nil, &block)
8
8
  name, loader_name, loader_variable_name = super
9
9
 
10
10
  define_method(loader_name) do
@@ -45,7 +45,7 @@ module N1Loader
45
45
  respond_to?("#{name}_loader")
46
46
  end
47
47
 
48
- def n1_load(name, loader = nil, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
48
+ def n1_optimized(name, loader = nil, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
49
49
  loader ||= Class.new(N1Loader::Loader) do
50
50
  if block&.arity&.positive?
51
51
  define_method(:perform, &block)
@@ -6,8 +6,27 @@ module N1Loader
6
6
  # Subclasses must define +perform+ method that accepts single argument
7
7
  # and returns hash where key is the element and value is what we want to load.
8
8
  class Loader
9
- def self.arguments_key(*args)
10
- args.map(&:object_id)
9
+ class << self
10
+ attr_reader :arguments
11
+
12
+ # Defines an argument that can be accessed within the loader.
13
+ #
14
+ # First defined argument will have the value of first passed argument,
15
+ # meaning the order is important.
16
+ def argument(name)
17
+ @arguments ||= []
18
+ index = @arguments.size
19
+ define_method(name) { args[index] }
20
+ @arguments << name
21
+ end
22
+
23
+ # Defines a custom cache key that is calculated for passed arguments.
24
+ def cache_key(&block)
25
+ define_method(:cache_key) do
26
+ check_arguments!
27
+ instance_exec(&block)
28
+ end
29
+ end
11
30
  end
12
31
 
13
32
  def initialize(elements, *args)
@@ -24,10 +43,21 @@ module N1Loader
24
43
  loaded[element]
25
44
  end
26
45
 
46
+ def cache_key
47
+ args.map(&:object_id)
48
+ end
49
+
27
50
  private
28
51
 
29
52
  attr_reader :elements, :args
30
53
 
54
+ def check_arguments!
55
+ return unless (required = self.class.arguments)
56
+ return if required.size == args.size
57
+
58
+ raise MissingArgument, "Loader defined #{required.size} arguments but #{args.size} were given"
59
+ end
60
+
31
61
  def perform(_elements)
32
62
  raise NotImplemented, "Subclasses have to implement the method"
33
63
  end
@@ -36,9 +66,11 @@ module N1Loader
36
66
  @loaded[element] = value
37
67
  end
38
68
 
39
- def loaded
69
+ def loaded # rubocop:disable Metrics/AbcSize
40
70
  return @loaded if @loaded
41
71
 
72
+ check_arguments!
73
+
42
74
  @loaded = {}.compare_by_identity
43
75
 
44
76
  if elements.size == 1 && respond_to?(:single)
@@ -11,7 +11,9 @@ module N1Loader
11
11
  end
12
12
 
13
13
  def with(*args)
14
- loaders[loader_class.arguments_key(*args)] ||= loader_class.new(elements, *args)
14
+ loader = loader_class.new(elements, *args)
15
+
16
+ loaders[loader.cache_key] ||= loader
15
17
  end
16
18
 
17
19
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module N1Loader
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/n1_loader.rb CHANGED
@@ -12,4 +12,5 @@ module N1Loader # :nodoc:
12
12
  class NotImplemented < Error; end
13
13
  class NotLoaded < Error; end
14
14
  class NotFilled < Error; end
15
+ class MissingArgument < Error; end
15
16
  end
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.2.0
4
+ version: 1.3.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: 2022-01-14 00:00:00.000000000 Z
11
+ date: 2022-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord