Skip to content

Commit

Permalink
Support relations with a composite primary key
Browse files Browse the repository at this point in the history
  • Loading branch information
nvasilevski committed Mar 28, 2023
1 parent 6116fed commit 24c3053
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 4 deletions.
7 changes: 5 additions & 2 deletions lib/job-iteration/active_record_cursor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ def initialize
end

def initialize(relation, columns = nil, position = nil)
columns ||= "#{relation.table_name}.#{relation.primary_key}"
@columns = Array.wrap(columns)
@columns = if columns
Array(columns)
else
Array(relation.primary_key).map { |pk| "#{relation.table_name}.#{pk}" }
end
self.position = Array.wrap(position)
raise ArgumentError, "Must specify at least one column" if columns.empty?
if relation.joins_values.present? && !@columns.all? { |column| column.to_s.include?(".") }
Expand Down
6 changes: 5 additions & 1 deletion lib/job-iteration/active_record_enumerator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ class ActiveRecordEnumerator
def initialize(relation, columns: nil, batch_size: 100, cursor: nil)
@relation = relation
@batch_size = batch_size
@columns = Array(columns || "#{relation.table_name}.#{relation.primary_key}")
@columns = if columns
Array(columns)
else
Array(relation.primary_key).map { |pk| "#{relation.table_name}.#{pk}" }
end
@cursor = cursor
end

Expand Down
12 changes: 11 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def enqueue_at(job, _delay)
class Product < ActiveRecord::Base
end

class TravelRoute < ActiveRecord::Base
self.primary_key = [:origin, :destination]
end

host = ENV["USING_DEV"] == "1" ? "job-iteration.railgun" : "localhost"

connection_config = {
Expand All @@ -68,11 +72,16 @@ class Product < ActiveRecord::Base
config.redis = { host: host }
end

ActiveRecord::Base.connection.create_table(Product.table_name, force: true) do |t|
ActiveRecord::Base.connection.create_table(:products, force: true) do |t|
t.string(:name)
t.timestamps
end

ActiveRecord::Base.connection.create_table(:travel_routes, force: true, primary_key: [:origin, :destination]) do |t|
t.string(:destination)
t.string(:origin)
end

module LoggingHelpers
def assert_logged(message)
old_logger = ActiveJob::Base.logger
Expand Down Expand Up @@ -124,6 +133,7 @@ def insert_fixtures
end

def truncate_fixtures
ActiveRecord::Base.connection.truncate(TravelRoute.table_name)
ActiveRecord::Base.connection.truncate(Product.table_name)
end
end
13 changes: 13 additions & 0 deletions test/unit/active_record_enumerator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ class ActiveRecordEnumeratorTest < IterationUnitTest
assert_equal(10, enum.size)
end

test "enumerator for a relation with a composite primary key" do
TravelRoute.create!(origin: "A", destination: "B")
TravelRoute.create!(origin: "A", destination: "C")
TravelRoute.create!(origin: "B", destination: "A")

enum = build_enumerator(relation: TravelRoute.all, batch_size: 2)

cursors = []
enum.records.each { |_record, cursor| cursors << cursor }

assert_equal([["A", "B"], ["A", "C"], ["B", "A"]], cursors)
end if ActiveRecord.version >= Gem::Version.new("7.1.0.alpha")

private

def build_enumerator(relation: Product.all, batch_size: 2, columns: nil, cursor: nil)
Expand Down

0 comments on commit 24c3053

Please sign in to comment.