batch-loader 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +44 -0
- data/lib/batch_loader.rb +5 -3
- data/lib/batch_loader/executor_proxy.rb +2 -2
- data/lib/batch_loader/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa05684af093fc9efd4873f256fd0a173179609c
|
4
|
+
data.tar.gz: 9e7e5751b5bba6b43f0cf8bce0e32fd64885a194
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08d5499226c25e153e4587358e8f38cd88950fe4d216578ea5b82b71f77ca381bd07f0383bda26e54edd56ffb4c92b458028857f1db7d770101039c548d0838e'
|
7
|
+
data.tar.gz: '02913dc9ee5cc57e952ecd49a7636d275d7343990c574a3f14ff0ddf7ed662991cfdd4f8b722c0dcca54b86996d9a4377ebf4f5582075bf54670657dc8c0c30d'
|
data/CHANGELOG.md
CHANGED
@@ -8,10 +8,14 @@ one of the following labels: `Added`, `Changed`, `Deprecated`,
|
|
8
8
|
to manage the versions of this gem so
|
9
9
|
that you can set version constraints properly.
|
10
10
|
|
11
|
-
#### [Unreleased](https://github.com/exAspArk/batch-loader/compare/v1.
|
11
|
+
#### [Unreleased](https://github.com/exAspArk/batch-loader/compare/v1.2.0...HEAD)
|
12
12
|
|
13
13
|
* WIP
|
14
14
|
|
15
|
+
#### [v1.2.0](https://github.com/exAspArk/batch-loader/compare/v1.1.1...v1.2.0)
|
16
|
+
|
17
|
+
* `Added`: `key` argument for the `BatchLoader#batch` method. [#12](https://github.com/exAspArk/batch-loader/pull/12)
|
18
|
+
|
15
19
|
#### [v1.1.1](https://github.com/exAspArk/batch-loader/compare/v1.1.0...v1.1.1)
|
16
20
|
|
17
21
|
* `Fixed`: `loader`, made it thread-safe again. [#10](https://github.com/exAspArk/batch-loader/pull/10)
|
data/README.md
CHANGED
@@ -18,8 +18,10 @@ This gem provides a generic lazy batching mechanism to avoid N+1 DB queries, HTT
|
|
18
18
|
* [RESTful API example](#restful-api-example)
|
19
19
|
* [GraphQL example](#graphql-example)
|
20
20
|
* [Loading multiple items](#loading-multiple-items)
|
21
|
+
* [Batch key](#batch-key)
|
21
22
|
* [Caching](#caching)
|
22
23
|
* [Installation](#installation)
|
24
|
+
* [API](#api)
|
23
25
|
* [Implementation details](#implementation-details)
|
24
26
|
* [Development](#development)
|
25
27
|
* [Contributing](#contributing)
|
@@ -300,6 +302,30 @@ BatchLoader.for(user.id).batch(default_value: []) do |comment_ids, loader|
|
|
300
302
|
end
|
301
303
|
```
|
302
304
|
|
305
|
+
### Batch key
|
306
|
+
|
307
|
+
It's possible to reuse the same `BatchLoader#batch` block for loading different types of data by specifying a unique `key`.
|
308
|
+
For example, with polymorphic associations:
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
def lazy_association(post)
|
312
|
+
id = post.association_id
|
313
|
+
key = post.association_type
|
314
|
+
|
315
|
+
BatchLoader.for(id).batch(key: key) do |ids, loader, args|
|
316
|
+
model = Object.const_get(args[:key])
|
317
|
+
model.where(id: ids).each { |record| record.call(record.id, record) }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
post1 = Post.save(association_id: 1, association_type: 'Tag')
|
321
|
+
post2 = Post.save(association_id: 1, association_type: 'Category')
|
322
|
+
|
323
|
+
lazy_association(post1) # SELECT * FROM tags WHERE id IN (1)
|
324
|
+
lazy_association(post2) # SELECT * FROM categories WHERE id IN (1)
|
325
|
+
```
|
326
|
+
|
327
|
+
It's also required to pass custom `key` when using `BatchLoader` with metaprogramming (e.g. `eval`).
|
328
|
+
|
303
329
|
### Caching
|
304
330
|
|
305
331
|
By default `BatchLoader` caches the loaded values. You can test it by running something like:
|
@@ -364,6 +390,24 @@ Or install it yourself as:
|
|
364
390
|
|
365
391
|
$ gem install batch-loader
|
366
392
|
|
393
|
+
## API
|
394
|
+
|
395
|
+
```ruby
|
396
|
+
BatchLoader.for(item).batch(default_value: default_value, cache: cache, key: key) do |items, loader, args|
|
397
|
+
# ...
|
398
|
+
end
|
399
|
+
```
|
400
|
+
|
401
|
+
| Argument Key | Default | Description |
|
402
|
+
| --------------- | --------------------------------------------- | ------------------------------------------------------------- |
|
403
|
+
| `item` | - | Item which will be collected and used for batching. |
|
404
|
+
| `default_value` | `nil` | Value returned by default after batching. |
|
405
|
+
| `cache` | `true` | Set `false` to disable caching between the same executions. |
|
406
|
+
| `key` | `nil` | Pass custom key to uniquely identify the batch block. |
|
407
|
+
| `items` | - | List of collected items for batching. |
|
408
|
+
| `loader` | - | Lambda which should be called to load values loaded in batch. |
|
409
|
+
| `args` | `{default_value: nil, cache: true, key: nil}` | Arguments passed to the `batch` method. |
|
410
|
+
|
367
411
|
## Implementation details
|
368
412
|
|
369
413
|
See the [slides](https://speakerdeck.com/exaspark/batching-a-powerful-way-to-solve-n-plus-1-queries) [37-42].
|
data/lib/batch_loader.rb
CHANGED
@@ -23,9 +23,10 @@ class BatchLoader
|
|
23
23
|
@__executor_proxy = executor_proxy
|
24
24
|
end
|
25
25
|
|
26
|
-
def batch(default_value: nil, cache: true, &batch_block)
|
26
|
+
def batch(default_value: nil, cache: true, key: nil, &batch_block)
|
27
27
|
@default_value = default_value
|
28
28
|
@cache = cache
|
29
|
+
@key = key
|
29
30
|
@batch_block = batch_block
|
30
31
|
__executor_proxy.add(item: @item)
|
31
32
|
|
@@ -78,7 +79,8 @@ class BatchLoader
|
|
78
79
|
|
79
80
|
items = __executor_proxy.list_items
|
80
81
|
loader = __loader
|
81
|
-
@
|
82
|
+
args = {default_value: @default_value, cache: @cache, key: @key}
|
83
|
+
@batch_block.call(items, loader, args)
|
82
84
|
items.each do |item|
|
83
85
|
next if __executor_proxy.value_loaded?(item: item)
|
84
86
|
loader.call(item, @default_value)
|
@@ -126,7 +128,7 @@ class BatchLoader
|
|
126
128
|
def __executor_proxy
|
127
129
|
@__executor_proxy ||= begin
|
128
130
|
raise NoBatchError.new("Please provide a batch block first") unless @batch_block
|
129
|
-
BatchLoader::ExecutorProxy.new(@default_value, &@batch_block)
|
131
|
+
BatchLoader::ExecutorProxy.new(@default_value, @key, &@batch_block)
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
@@ -6,10 +6,10 @@ class BatchLoader
|
|
6
6
|
class ExecutorProxy
|
7
7
|
attr_reader :default_value, :block, :global_executor
|
8
8
|
|
9
|
-
def initialize(default_value, &block)
|
9
|
+
def initialize(default_value, key, &block)
|
10
10
|
@default_value = default_value
|
11
11
|
@block = block
|
12
|
-
@block_hash_key = block.source_location
|
12
|
+
@block_hash_key = "#{key}#{block.source_location}"
|
13
13
|
@global_executor = BatchLoader::Executor.ensure_current
|
14
14
|
end
|
15
15
|
|
data/lib/batch_loader/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: batch-loader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- exAspArk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|