Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/staging_table/bulk_inserter.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "json"

module StagingTable
class BulkInserter
attr_reader :model, :batch_size
Expand Down Expand Up @@ -37,7 +39,12 @@ def connection
end

def quote(value)
connection.quote(value)
case value
when Array, Hash
connection.quote(value.to_json)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The to_json method is being used without explicitly requiring the JSON library. While ActiveSupport provides to_json for Array and Hash, it would be more robust to add require "json" at the top of this file to ensure the method is available, especially if this library is used in contexts where ActiveSupport might not load all core extensions.

Copilot uses AI. Check for mistakes.
else
connection.quote(value)
end
end
end
end
28 changes: 28 additions & 0 deletions spec/staging_table/bulk_inserter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,40 @@
end
end

shared_examples "bulk inserter with JSON support" do
describe "#insert with JSON" do
it "handles array values for JSON/JSONB columns" do
records = [
{name: "John", email: "john@example.com", tags: %w[admin user]}
]

inserter.insert(records)

user = staging_model.first
expect(user.tags).to eq(%w[admin user])
end

it "handles hash values for JSON/JSONB columns" do
records = [
{name: "John", email: "john@example.com", metadata: {role: "admin", level: 5}}
]

inserter.insert(records)

user = staging_model.first
expect(user.metadata).to eq({"role" => "admin", "level" => 5})
end
end
Comment on lines +93 to +114
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding test cases for edge cases with JSON columns, such as: empty arrays ([]), empty hashes ({}), nested structures, and null values for JSON columns. These would help ensure the JSON serialization handles all scenarios correctly.

Copilot uses AI. Check for mistakes.
end

context "with PostgreSQL", :postgresql do
include_examples "bulk inserter"
include_examples "bulk inserter with JSON support"
end

context "with MySQL", :mysql do
include_examples "bulk inserter"
include_examples "bulk inserter with JSON support"
end

context "with SQLite", :sqlite do
Expand Down
6 changes: 6 additions & 0 deletions spec/support/database_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,17 @@ def create_test_tables
DROP TABLE IF EXISTS test_users
SQL

json_type = /postgresql/.match?(ActiveRecord::Base.connection.adapter_name.downcase) ? "JSONB" : "JSON"

ActiveRecord::Base.connection.execute(<<~SQL)
CREATE TABLE test_users (
id SERIAL PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
age INTEGER,
active BOOLEAN DEFAULT true,
tags #{json_type},
metadata #{json_type},
created_at TIMESTAMP,
updated_at TIMESTAMP
)
Expand All @@ -219,6 +223,8 @@ def create_sqlite_test_tables
email VARCHAR(255),
age INTEGER,
active BOOLEAN DEFAULT 1,
tags TEXT,
metadata TEXT,
created_at DATETIME,
updated_at DATETIME
)
Expand Down