prelude-batch-loader 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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: []