better_batch-active_record 1.0.3 → 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
  SHA256:
3
- metadata.gz: fbe9b288ca345597bef98eb96b6cc5f502d2e3fc80e5cb93d37ae7fa2e58d0f5
4
- data.tar.gz: f2630014996f4a63aa776d3c5874ed0069fbb1a132e3c8c56debabbfc156a4e9
3
+ metadata.gz: a12d961c7d5053c050e5ddb15db2a538c1ac45d60b95a4e30fcc3cfd4350b0e3
4
+ data.tar.gz: a3bb810a265d30d681a51bf01b5c774aa66fb805a318f8cbcad57109eb1c1ad9
5
5
  SHA512:
6
- metadata.gz: a9f48bb98fa537624fdf5184e1ef79ec71bc5eb7c6057c6d1aaa9779a3e394ca4c522859b22cd5c577cc518dcb22b9ee4116ccc8306858341aec503241a8c8a8
7
- data.tar.gz: 9ad9b8c1f33a5c224952a1fba2253b0e955fcf9ca05edce4ca42545c5c1113053cd8515166d21f88e8fb713ce9055ccb64ec1b3813e59c290839c6dc09bff3e3
6
+ metadata.gz: 48766522a43487d0be9514d148ad431408ef219333dd4a3ee69de8f4a902e77989cbe7785152d6ae5ee1a11d94eed1750085e3513baf4a05094a5cd54d4c272b
7
+ data.tar.gz: ed282d59658f40fb23aa6dfbe0a2212aeb854e8001778879e2b8c4daa5f05cb33582d132532dd659f5b677c4a865544139b3c3a3f4cd3f7828b4ba00e7e830b9
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'better_batch/query'
4
+ require 'better_batch/active_record/query'
5
+ require 'better_batch/active_record/transform'
6
+
7
+ module BetterBatch
8
+ module ActiveRecord
9
+ class Interface
10
+ def initialize(model)
11
+ @builder = Query.new(model)
12
+ @model = model
13
+ end
14
+
15
+ def upsert(data, unique_by:, except: nil, returning: nil)
16
+ upsert_data = Transform.slice_upsert(data, except:)
17
+ query = builder.build(upsert_data, unique_by:, returning:)
18
+ result = exec_query(:upsert, query, upsert_data)
19
+ Transform.build_return(returning, result.rows, query)
20
+ end
21
+
22
+ def with_upserted_pk(data, unique_by:, except: nil, &)
23
+ upserted = upsert(data, unique_by:, except:, returning: primary_key)
24
+ if block_given?
25
+ data.zip(upserted, &)
26
+ else
27
+ data.zip(upserted)
28
+ end
29
+ end
30
+
31
+ def set_upserted_pk(data, unique_by:, except: nil)
32
+ if block_given?
33
+ with_upserted_pk(data, unique_by:, except:) do |row, pk|
34
+ row[primary_key] = pk
35
+ yield row
36
+ end
37
+ else
38
+ set_upserted_pk_map(data, unique_by:, except:)
39
+ end
40
+ end
41
+
42
+ def select(data, unique_by:, returning:)
43
+ Transform.assert_inputs_ok!(data, unique_by:)
44
+ select_data = data.map { |datum| datum.slice(*unique_by) }
45
+ query = builder.build(select_data, unique_by:, returning:)
46
+ result = exec_query(:select, query, select_data)
47
+ Transform.build_return(returning, result.rows, query)
48
+ end
49
+
50
+ def with_selected_pk(data, unique_by:, &)
51
+ selected = select(data, unique_by:, returning: primary_key)
52
+ if block_given?
53
+ data.zip(selected, &)
54
+ else
55
+ data.zip(selected)
56
+ end
57
+ end
58
+
59
+ def set_selected_pk(data, unique_by:)
60
+ if block_given?
61
+ with_selected_pk(data, unique_by:) do |row, pk|
62
+ row[primary_key] = pk
63
+ yield row
64
+ end
65
+ else
66
+ set_selected_pk_map(data, unique_by:)
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :model, :builder
73
+
74
+ def set_upserted_pk_map(data, unique_by:, except: nil)
75
+ with_upserted_pk(data, unique_by:, except:).map do |row, pk|
76
+ row[primary_key] = pk
77
+ row
78
+ end
79
+ end
80
+
81
+ def set_selected_pk_map(data, unique_by:)
82
+ with_selected_pk(data, unique_by:).map do |row, pk|
83
+ row[primary_key] = pk
84
+ row
85
+ end
86
+ end
87
+
88
+ def exec_query(type, query, data)
89
+ db_exec(query.public_send(type), JSON.generate(data))
90
+ end
91
+
92
+ def db_exec(sql, json_data)
93
+ model.connection.exec_query(sql, nil, [json_data])
94
+ end
95
+
96
+ def primary_key
97
+ model.primary_key.to_sym
98
+ end
99
+ end
100
+ end
101
+ end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_batch/active_record/query'
3
+ require 'better_batch/active_record/interface'
4
4
 
5
5
  module BetterBatch
6
6
  module ActiveRecord
7
7
  module Model
8
8
  def better_batch
9
- Query.new(self)
9
+ Interface.new(self)
10
10
  end
11
11
  end
12
12
  end
@@ -9,90 +9,15 @@ module BetterBatch
9
9
  @model = model
10
10
  end
11
11
 
12
- def upsert(data, unique_by:, except: nil, returning: nil)
13
- upsert_data = slice_upsert(data, except:)
14
- query = build_query(upsert_data, unique_by:, returning:)
15
- result = exec_query(:upsert, query, upsert_data)
16
- build_return(returning, result.rows, query)
17
- end
18
-
19
- def with_upserted_pk(data, unique_by:, except: nil)
20
- upserted = upsert(data, unique_by:, except:, returning: primary_key)
21
- data.zip(upserted)
22
- end
23
-
24
- def set_upserted_pk(data, unique_by:, except: nil)
25
- with_upserted_pk(data, unique_by:, except:).each do |row, pk|
26
- row[primary_key] = pk
27
- end
28
- nil
29
- end
30
-
31
- def select(data, unique_by:, returning:)
32
- assert_inputs_ok!(data, unique_by:)
33
- select_data = data.map { |datum| datum.slice(*unique_by) }
34
- query = build_query(select_data, unique_by:, returning:)
35
- result = exec_query(:select, query, select_data)
36
- build_return(returning, result.rows, query)
37
- end
38
-
39
- def build_return(returning, rows, query)
40
- case returning
41
- when Symbol
42
- rows.map(&:first)
43
- when nil, []
44
- nil
45
- else
46
- hash_rows(query.returning, rows)
47
- end
48
- end
49
-
50
- def with_selected_pk(data, unique_by:)
51
- data.zip(select(data, unique_by:, returning: primary_key))
52
- end
53
-
54
- def set_selected_pk(data, unique_by:)
55
- with_upserted_pk(data, unique_by:).each do |row, pk|
56
- row[primary_key] = pk
57
- end
58
- nil
59
- end
60
-
61
- private
62
-
63
- attr_reader :model
64
-
65
- def slice_upsert(data, except:)
66
- case except
67
- when nil, []
68
- data
69
- else
70
- data.map { |datum| datum.except(*except) }
71
- end
72
- end
73
-
74
- def assert_inputs_ok!(data, unique_by:)
75
- data_keys = data.first.keys
76
- missing = Array(unique_by) - data_keys
77
- return if missing.empty?
78
-
79
- msg = "All unique_by columns must be in the given data, but #{missing.inspect} was missing from #{data_keys}."
80
- raise Error, msg
81
- end
82
-
83
- def build_query(data, unique_by:, returning:)
12
+ def build(data, unique_by:, returning:)
84
13
  BetterBatch::Query.new(table_name:, primary_key:, input_columns: data.first.keys,
85
14
  column_types:, unique_columns: unique_by, now_on_insert:,
86
15
  now_on_update:, returning:)
87
16
  end
88
17
 
89
- def exec_query(type, query, data)
90
- db_exec(query.public_send(type), JSON.generate(data))
91
- end
18
+ private
92
19
 
93
- def db_exec(sql, json_data)
94
- model.connection.exec_query(sql, nil, [json_data])
95
- end
20
+ attr_reader :model
96
21
 
97
22
  def table_name
98
23
  @table_name ||= model.table_name
@@ -121,15 +46,6 @@ module BetterBatch
121
46
  def updated_at_if_present
122
47
  :updated_at if column_types.key?(:updated_at)
123
48
  end
124
-
125
- def hash_rows(returning, rows)
126
- # avoid building an entire new hash (which would rehash keys) for each row
127
- # we only need to sub in the values
128
- indexes = returning.each_with_index.to_h.freeze
129
- rows.map do |row|
130
- indexes.transform_values { |index| row[index] }
131
- end
132
- end
133
49
  end
134
50
  end
135
51
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'better_batch/query'
4
+ require 'better_batch/active_record/query'
5
+
6
+ module BetterBatch
7
+ module ActiveRecord
8
+ module Transform
9
+ class << self
10
+ def assert_inputs_ok!(data, unique_by:)
11
+ data_keys = data.first.keys
12
+ missing = Array(unique_by) - data_keys
13
+ return if missing.empty?
14
+
15
+ msg = "All unique_by columns must be in the given data, but #{missing.inspect} was missing from #{data_keys}."
16
+ raise Error, msg
17
+ end
18
+
19
+ def slice_upsert(data, except:)
20
+ case except
21
+ when nil, []
22
+ data
23
+ else
24
+ data.map { |datum| datum.except(*except) }
25
+ end
26
+ end
27
+
28
+ def build_return(returning, rows, query)
29
+ case returning
30
+ when Symbol
31
+ rows.map(&:first)
32
+ when nil, []
33
+ nil
34
+ else
35
+ hash_rows(query.returning, rows)
36
+ end
37
+ end
38
+
39
+ def hash_rows(returning, rows)
40
+ # avoid building an entire new hash (which would rehash keys) for each row
41
+ # we only need to sub in the values
42
+ indexes = returning.each_with_index.to_h.freeze
43
+ rows.map do |row|
44
+ indexes.transform_values { |index| row[index] }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -9,6 +9,6 @@ module BetterBatch
9
9
  # because Rails is love, Rails is life, Rails is everything
10
10
  module Version; end
11
11
 
12
- VERSION = '1.0.3'
12
+ VERSION = '1.1.0'
13
13
  end
14
14
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_batch-active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Hartland
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-17 00:00:00.000000000 Z
10
+ date: 2025-04-18 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activerecord
@@ -53,8 +53,10 @@ files:
53
53
  - lib/better_batch/.DS_Store
54
54
  - lib/better_batch/active_record.rb
55
55
  - lib/better_batch/active_record/error.rb
56
+ - lib/better_batch/active_record/interface.rb
56
57
  - lib/better_batch/active_record/model.rb
57
58
  - lib/better_batch/active_record/query.rb
59
+ - lib/better_batch/active_record/transform.rb
58
60
  - lib/better_batch/active_record/version.rb
59
61
  homepage: https://github.com/th7/better_batch-active_record
60
62
  licenses: