prelude-batch-loader 0.0.4 → 0.0.5

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: cae99a6ad46de71ce518e50d1f2877efaebf2df5d23b4224fb10416417f69cd6
4
- data.tar.gz: 3594cbeadbaa4e55fea9138570fc55fd8863c04698999737cb018290af95f310
3
+ metadata.gz: f86743d57a4562218bfea1d13a8e9e920a0ca5f9a91085607f1d1afe5d335e62
4
+ data.tar.gz: 2778e3c72e362cea60a81d49a04e86deea59227079d870d4351ec0303e105cd0
5
5
  SHA512:
6
- metadata.gz: 9519329f8ed99362489e9b434448879b1aae9c286e4b689b8b8376866e5b327fd055fcccd36e3e2edb7a4765ca2a478b26b24084808ca7d81b8e2520d261262a
7
- data.tar.gz: c2e34af07621b2b2a06514eee82d010f867b67f4afefa50811a239f2536e0bbda6cc168a25f6c5138b5e922d7a012d4ce4c1e670537d2284da4c9f0a745e2bd7
6
+ metadata.gz: 41b1b1bae958e1641b8b08c779f7ee56470198f91463a9d2afeeea58de88577b184858fc00802661dce66de1a0814c4ab238fc7dd1e9c6c52bcf6bb17b0801ca
7
+ data.tar.gz: b99d979848d04d2a390f98cc806221f6124662fb2d13b4eb37cb3625c8422496594a1825e5e813eb7e1b747f8314e0d08ca3a29b99c4aef5a1869d14b2427870
data/lib/prelude.rb CHANGED
@@ -3,6 +3,17 @@ require_relative 'prelude/preloadable'
3
3
  require_relative 'prelude/enumerator'
4
4
  require 'active_support'
5
5
 
6
+ module Prelude
7
+ def self.wrap(records)
8
+ preloader = Preloader.new(records.first.class, records)
9
+ records.each { |r| r.prelude_preloader = preloader }
10
+ end
11
+
12
+ def self.preload(records, method)
13
+ wrap(records).each(&method)
14
+ end
15
+ end
16
+
6
17
  ActiveSupport.on_load :active_record do
7
18
  include Prelude::Preloadable
8
19
  end
@@ -8,8 +8,7 @@ module Prelude
8
8
  raise TypeMismatch unless map(&:class).uniq.count == 1
9
9
 
10
10
  # Share a preloader
11
- preloader = Preloader.new(first.class, self)
12
- each { |r| r.prelude_preloader = preloader }
11
+ Prelude.wrap(self)
13
12
 
14
13
  # Iterate
15
14
  each { |o| yield o }
@@ -1,9 +1,6 @@
1
1
  module Prelude
2
2
  class Method
3
- attr_reader :batch_size
4
-
5
- def initialize(batch_size:, &blk)
6
- @batch_size = batch_size
3
+ def initialize(&blk)
7
4
  @definition = blk
8
5
  end
9
6
 
@@ -7,6 +7,15 @@ module Prelude
7
7
 
8
8
  attr_writer :prelude_preloader
9
9
 
10
+ def preloaded_values
11
+ @preloaded_values ||= {}
12
+ end
13
+
14
+ def set_preloaded_value_for(name, args, result)
15
+ key = [name, args]
16
+ preloaded_values[key] = result
17
+ end
18
+
10
19
  class_methods do
11
20
  # Mapping of field name to block for resolving a given preloader
12
21
  def prelude_methods
@@ -14,15 +23,19 @@ module Prelude
14
23
  end
15
24
 
16
25
  # Define how to preload a given method
17
- def define_prelude(name, batch_size: nil, &blk)
18
- prelude_methods[name] = Prelude::Method.new(batch_size: batch_size, &blk)
26
+ def define_prelude(name, &blk)
27
+ prelude_methods[name] = Prelude::Method.new(&blk)
19
28
 
20
29
  define_method(name) do |*args|
30
+ key = [name, args]
31
+ return preloaded_values[key] if preloaded_values.key?(key)
32
+
21
33
  unless @prelude_preloader
22
34
  @prelude_preloader = Preloader.new(self.class, [self])
23
35
  end
24
36
 
25
- @prelude_preloader.fetch(name, self, *args)
37
+ @prelude_preloader.fetch(name, *args)
38
+ preloaded_values[key]
26
39
  end
27
40
  end
28
41
  end
@@ -3,59 +3,25 @@ module Prelude
3
3
  def initialize(klass, records)
4
4
  @klass = klass
5
5
  @records = records
6
- @runs = {}
7
6
  end
8
7
 
9
- def fetch(name, object, *args)
8
+ def fetch(name, *args)
10
9
  method = @klass.prelude_methods.fetch(name)
11
10
 
12
- # If this object has a run, return the value
13
- if run = run_for(method, args, object)
14
- return run[object]
11
+ # Load and set the results for each record
12
+ results = preload(method, args)
13
+ @records.each do |record|
14
+ record.set_preloaded_value_for(name, args, results[record])
15
15
  end
16
16
 
17
- # Choose a batch of the correct size that contains the object we're trying to load,
18
- # or use all if we're not batching
19
- run = if method.batch_size
20
- remaining_records = @records.to_a - resolved_objects_for(method, args)
21
- slices = remaining_records.each_slice(method.batch_size)
22
- slice = slices.detect { |slice| slice.include?(object) }
23
- preload(method, slice, args)
24
- else
25
- preload(method, @records, args)
26
- end
27
-
28
- # Return the value for this object
29
- run[object]
17
+ results
30
18
  end
31
19
 
32
20
  private
33
21
 
34
22
  # Preload the given field with the given args for all records
35
- def preload(method, records, args)
36
- results = method.call(records, *args)
37
-
38
- # set the run for each of these name/record/args combos
39
- records.each do |record|
40
- set_run_for(method, args, record, results)
41
- end
42
-
43
- # Return the run
44
- results
45
- end
46
-
47
- def run_for(method, args, object)
48
- @runs.dig(method, args, object)
49
- end
50
-
51
- def resolved_objects_for(method, args)
52
- @runs.dig(method, args)&.keys || []
53
- end
54
-
55
- def set_run_for(method, args, object, run)
56
- @runs[method] ||= {}
57
- @runs[method][args] ||= {}
58
- @runs[method][args][object] = run
23
+ def preload(method, args)
24
+ method.call(@records, *args)
59
25
  end
60
26
  end
61
27
  end
@@ -1,3 +1,3 @@
1
1
  module Prelude
2
- VERSION = [0, 0, 4].join('.')
2
+ VERSION = [0, 0, 5].join('.')
3
3
  end
data/spec/prelude_spec.rb CHANGED
@@ -129,39 +129,24 @@ describe Prelude do
129
129
  ])
130
130
  end
131
131
 
132
- it 'should be able to set a batch size' do
132
+ it 'should preload when called explicitly' do
133
133
  call_count = 0
134
+ klass = Class.new do
135
+ include Prelude::Preloadable
134
136
 
135
- klass = Class.new(ActiveRecord::Base) do
136
- self.table_name = 'breweries'
137
-
138
- define_prelude(:number, batch_size: 2) do |records|
137
+ define_prelude(:foo) do |records|
139
138
  call_count += 1
140
- Hash[records.map { |r| [r, 42] }]
139
+ records.index_with("bar")
141
140
  end
142
141
  end
143
142
 
144
- values = 4.times.map { klass.new }.map.with_prelude { |r| r.number }
145
-
146
- expect(values.uniq).to eq([42])
147
- expect(call_count).to eq(4 / 2) # one per batch
148
- end
149
-
150
- it 'should be able to use batch_size with default_proc' do
151
- call_count = 0
152
-
153
- klass = Class.new(ActiveRecord::Base) do
154
- self.table_name = 'breweries'
155
-
156
- define_prelude(:number, batch_size: 2) do |records|
157
- call_count += 1
158
- Hash.new { |h, k| h[k] = 42 }
159
- end
160
- end
143
+ records = 4.times.map { klass.new }
144
+ expect(call_count).to eq(0)
161
145
 
162
- values = 4.times.map { klass.new }.map.with_prelude { |r| r.number }
146
+ Prelude.preload(records, :foo)
147
+ expect(call_count).to eq(1)
163
148
 
164
- expect(values.uniq).to eq([42])
165
- expect(call_count).to eq(4 / 2) # one per batch
149
+ expect(records.map(&:foo)).to eq(["bar"]*4)
150
+ expect(call_count).to eq(1)
166
151
  end
167
152
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require 'fileutils'
2
2
  require 'active_record'
3
3
  require 'pry'
4
- require_relative '../lib/prelude'
4
+
5
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
6
+ require 'prelude'
5
7
 
6
8
  # Remove existing
7
9
  FileUtils.rm_rf('db.sqlite3')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prelude-batch-loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Crepezzi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-27 00:00:00.000000000 Z
11
+ date: 2021-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -53,19 +53,33 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.4'
55
55
  - !ruby/object:Gem::Dependency
56
- name: pry-byebug
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '1'
82
+ version: '0'
69
83
  description:
70
84
  email: john.crepezzi@gmail.com
71
85
  executables: []