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 +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +21 -19
- data/lib/n1_loader/ar_lazy_preload/loadable.rb +1 -1
- data/lib/n1_loader/core/loadable.rb +1 -1
- data/lib/n1_loader/core/loader.rb +35 -3
- data/lib/n1_loader/core/loader_collection.rb +3 -1
- data/lib/n1_loader/version.rb +1 -1
- data/lib/n1_loader.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc47894a27d425f70a38dc43b9b40053d823f4815fe8e135a7cb1cf5afbde0f3
|
4
|
+
data.tar.gz: 132d5851c19763db2f1910ebeeb6a368437aba6d3340c2c69ad2ffe348791011
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 945258069b57bc7cd0fe26416411322886d734db0ed4eead1c88a3acced70bdb14ffc92eb9403e5d346c0853d64dc09e5afb8039a9026c9b4c09a1cc6f5fc9e8
|
7
|
+
data.tar.gz: 036e5a8a4b2d63bed2aee558164fdd042ac8c0c68b0ecdb1d5ec9f64231ca9f6841dc56cd6cdc63b87fdb9bf964e4f42089f89d9783cf2513cf81243a473150a
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
## [1.
|
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
|
-
|
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
|
-
|
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
|
-
|
101
|
+
|
102
|
+
n1_optimized :orders_count, OrdersCountLoader
|
103
103
|
end
|
104
104
|
|
105
105
|
class Customer
|
106
106
|
include N1Loader::Loadable
|
107
|
-
|
108
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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]) }
|
@@ -45,7 +45,7 @@ module N1Loader
|
|
45
45
|
respond_to?("#{name}_loader")
|
46
46
|
end
|
47
47
|
|
48
|
-
def
|
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
|
-
|
10
|
-
|
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)
|
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: 1.
|
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-
|
11
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|