batch-loader 1.1.1 → 1.2.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 +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
|