batch-loader 1.0.4 → 1.1.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
  SHA1:
3
- metadata.gz: 68e25c611b667937e94fa71fc53d7ca0e0610914
4
- data.tar.gz: bf88a43be0f71991ea587d9f1a9cd7de0c63310c
3
+ metadata.gz: 124dbf8b2fa20f0e0fd6bca686449f48c3dd3625
4
+ data.tar.gz: d10abd20d3f55f64871673b5410c8d92539abaa5
5
5
  SHA512:
6
- metadata.gz: 23317a63530d9067930446a9426f34f54b78d8a991c2901558b1c79558b7941291dedbfd58b843195cae19e6fac4288668a7176273c64320419dc4621ac23a16
7
- data.tar.gz: 5ce2b962b3948e6a579b1631e500d81c3a48e0eaa7bddf22fbbf00d081c39fda88beb6803531848fce5aa5bbe6e9ac243aaa69174e1127b5109cf7a1cd70cc96
6
+ metadata.gz: 4e97a8dcbb31e6310dc2b40df35143f6bdac4a1153b1ea9de175f07b36e8df0da7890e1c445f91c782e3ac1804ee0129107329685e0aac50dcafadbe17278c3a
7
+ data.tar.gz: 93188a2738ac3f57735e0643003818b19eb4875c2b748fbbf0e19751c837a8ba32247b84fa84533bb2bbe84515eb35fc28f31929813871c6eb21b9fc08a1d4b8
@@ -8,11 +8,16 @@ 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.0.4...HEAD)
11
+ #### [Unreleased](https://github.com/exAspArk/batch-loader/compare/v1.1.0...HEAD)
12
12
 
13
13
  * WIP
14
14
 
15
- #### [Unreleased](https://github.com/exAspArk/batch-loader/compare/v1.0.3...v1.0.4)
15
+ #### [v1.1.0](https://github.com/exAspArk/batch-loader/compare/v1.0.4...v1.1.0)
16
+
17
+ * `Added`: `default_value` override option. [#8](https://github.com/exAspArk/batch-loader/pull/8)
18
+ * `Added`: `loader.call {}` block syntax, for memoizing repeat calls to the same item. [#8](https://github.com/exAspArk/batch-loader/pull/8)
19
+
20
+ #### [v1.0.4](https://github.com/exAspArk/batch-loader/compare/v1.0.3...v1.0.4)
16
21
 
17
22
  * `Fixed`: Fix arity bug in `respond_to?` [#3](https://github.com/exAspArk/batch-loader/pull/3)
18
23
 
data/README.md CHANGED
@@ -17,6 +17,7 @@ This gem provides a generic lazy batching mechanism to avoid N+1 DB queries, HTT
17
17
  * [How it works](#how-it-works)
18
18
  * [RESTful API example](#restful-api-example)
19
19
  * [GraphQL example](#graphql-example)
20
+ * [Loading multiple items](#loading-multiple-items)
20
21
  * [Caching](#caching)
21
22
  * [Installation](#installation)
22
23
  * [Implementation details](#implementation-details)
@@ -279,6 +280,26 @@ end
279
280
 
280
281
  That's it.
281
282
 
283
+ ### Loading multiple items
284
+
285
+ For batches where there is no item in response to a call, we normally return `nil`. However, you can use `:default_value` to return something else instead:
286
+
287
+ ```ruby
288
+ BatchLoader.for(post.user_id).batch(default_value: NullUser.new) do |user_ids, loader|
289
+ User.where(id: user_ids).each { |user| loader.call(user.id, user) }
290
+ end
291
+ ```
292
+
293
+ For batches where the value is some kind of collection, such as an Array or Hash, `loader` also supports being called with a block, which yields the _current_ value, and returns the _next_ value. This is extremely useful for 1:Many relationships:
294
+
295
+ ```ruby
296
+ BatchLoader.for(user.id).batch(default_value: []) do |comment_ids, loader|
297
+ Comment.where(user_id: user_ids).each do |comment|
298
+ loader.call(user.id) { |memo| memo << comment }
299
+ end
300
+ end
301
+ ```
302
+
282
303
  ### Caching
283
304
 
284
305
  By default `BatchLoader` caches the loaded values. You can test it by running something like:
@@ -22,7 +22,8 @@ class BatchLoader
22
22
  @item = item
23
23
  end
24
24
 
25
- def batch(cache: true, &batch_block)
25
+ def batch(default_value: nil, cache: true, &batch_block)
26
+ @default_value = default_value
26
27
  @cache = cache
27
28
  @batch_block = batch_block
28
29
  __executor_proxy.add(item: @item)
@@ -75,12 +76,21 @@ class BatchLoader
75
76
  return if __executor_proxy.value_loaded?(item: @item)
76
77
 
77
78
  items = __executor_proxy.list_items
78
- loader = ->(item, value) { __executor_proxy.load(item: item, value: value) }
79
+ loader = -> (item, value = (no_value = true; nil), &block) {
80
+ if no_value && !block
81
+ raise ArgumentError, "Please pass a value or a block"
82
+ elsif block && !no_value
83
+ raise ArgumentError, "Please pass a value or a block, not both"
84
+ end
85
+
86
+ next_value = block ? block.call(__executor_proxy.loaded_value(item: item)) : value
87
+ __executor_proxy.load(item: item, value: next_value)
88
+ }
79
89
 
80
90
  @batch_block.call(items, loader)
81
91
  items.each do |item|
82
92
  next if __executor_proxy.value_loaded?(item: item)
83
- loader.call(item, nil) # use "nil" for not loaded item after succesfull batching
93
+ loader.call(item, @default_value)
84
94
  end
85
95
  __executor_proxy.delete(items: items)
86
96
  end
@@ -109,7 +119,7 @@ class BatchLoader
109
119
  def __executor_proxy
110
120
  @__executor_proxy ||= begin
111
121
  raise NoBatchError.new("Please provide a batch block first") unless @batch_block
112
- BatchLoader::ExecutorProxy.new(&@batch_block)
122
+ BatchLoader::ExecutorProxy.new(@default_value, &@batch_block)
113
123
  end
114
124
  end
115
125
 
@@ -4,9 +4,10 @@ require_relative "./executor"
4
4
 
5
5
  class BatchLoader
6
6
  class ExecutorProxy
7
- attr_reader :block, :global_executor
7
+ attr_reader :default_value, :block, :global_executor
8
8
 
9
- def initialize(&block)
9
+ def initialize(default_value, &block)
10
+ @default_value = default_value
10
11
  @block = block
11
12
  @block_hash_key = block.source_location
12
13
  @global_executor = BatchLoader::Executor.ensure_current
@@ -29,7 +30,11 @@ class BatchLoader
29
30
  end
30
31
 
31
32
  def loaded_value(item:)
32
- loaded[item]
33
+ if value_loaded?(item: item)
34
+ loaded[item]
35
+ else
36
+ @default_value.dup
37
+ end
33
38
  end
34
39
 
35
40
  def value_loaded?(item:)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class BatchLoader
4
- VERSION = "1.0.4"
4
+ VERSION = "1.1.0"
5
5
  end
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.0.4
4
+ version: 1.1.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-10-12 00:00:00.000000000 Z
11
+ date: 2017-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler