Commit 150901e1 authored by Kamil Trzciński's avatar Kamil Trzciński

Fix support for jsonb/enum for insert_all

This fix is needed to properly support
columns that perform data mutation to a SQL datatype
ex. would be `jsonb` and `enum`
parent a4b03f35
...@@ -160,9 +160,7 @@ module BulkInsertSafe ...@@ -160,9 +160,7 @@ module BulkInsertSafe
attributes = {} attributes = {}
column_names.each do |name| column_names.each do |name|
value = item.read_attribute(name) attributes[name] = item.read_attribute(name)
value = item.type_for_attribute(name).serialize(value) # rubocop:disable Cop/ActiveRecordSerialize
attributes[name] = value
end end
_bulk_insert_reject_primary_key!(attributes, item.class.primary_key) _bulk_insert_reject_primary_key!(attributes, item.class.primary_key)
......
# frozen_string_literal: true
# This fix is needed to properly support
# columns that perform data mutation to a SQL datatype
# ex. would be `jsonb` and `enum`
#
# This is covered by tests in `BulkInsertSafe`
# that validates handling of different data types
if Rails.gem_version > Gem::Version.new("6.0.2")
raise Gem::DependencyError,
"Remove patch once the https://github.com/rails/rails/pull/38763 is included"
end
module ActiveRecordInsertAllBuilderMixin
def extract_types_from_columns_on(table_name, keys:)
columns = connection.schema_cache.columns_hash(table_name)
unknown_column = (keys - columns.keys).first
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
keys.index_with { |key| model.type_for_attribute(key) }
end
end
ActiveRecord::InsertAll::Builder.prepend(ActiveRecordInsertAllBuilderMixin)
...@@ -7,7 +7,7 @@ describe BulkInsertSafe do ...@@ -7,7 +7,7 @@ describe BulkInsertSafe do
include BulkInsertSafe include BulkInsertSafe
include ShaAttribute include ShaAttribute
validates :name, :enum_value, :secret_value, :sha_value, presence: true validates :name, :enum_value, :secret_value, :sha_value, :jsonb_value, presence: true
ENUM_VALUES = { ENUM_VALUES = {
case_1: 1 case_1: 1
...@@ -26,6 +26,7 @@ describe BulkInsertSafe do ...@@ -26,6 +26,7 @@ describe BulkInsertSafe do
default_value_for :enum_value, 'case_1' default_value_for :enum_value, 'case_1'
default_value_for :secret_value, 'my-secret' default_value_for :secret_value, 'my-secret'
default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12' default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
default_value_for :jsonb_value, { "key" => "value" }
def self.valid_list(count) def self.valid_list(count)
Array.new(count) { |n| new(name: "item-#{n}") } Array.new(count) { |n| new(name: "item-#{n}") }
...@@ -60,6 +61,7 @@ describe BulkInsertSafe do ...@@ -60,6 +61,7 @@ describe BulkInsertSafe do
t.text :encrypted_secret_value, null: false t.text :encrypted_secret_value, null: false
t.string :encrypted_secret_value_iv, null: false t.string :encrypted_secret_value_iv, null: false
t.binary :sha_value, null: false, limit: 20 t.binary :sha_value, null: false, limit: 20
t.jsonb :jsonb_value, null: false
t.index :name, unique: true t.index :name, unique: true
end end
...@@ -114,7 +116,7 @@ describe BulkInsertSafe do ...@@ -114,7 +116,7 @@ describe BulkInsertSafe do
described_class.bulk_insert!(items) described_class.bulk_insert!(items)
attribute_names = described_class.attribute_names - %w[id] attribute_names = described_class.attribute_names - %w[id created_at updated_at]
expect(described_class.last(items.size).pluck(*attribute_names)).to eq( expect(described_class.last(items.size).pluck(*attribute_names)).to eq(
items.pluck(*attribute_names)) items.pluck(*attribute_names))
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment