Skip to content

Commit

Permalink
Fix #843: recursive_on_duplicate_key_update doesn't work with non-sta…
Browse files Browse the repository at this point in the history
…ndard association name
  • Loading branch information
jacob-carlborg-apoex committed Sep 17, 2024
1 parent 65309cf commit 2405beb
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## Unreleased

### Breaking Changes

* Fix `recursive_on_duplicate_key_update` doesn't work with non-standard
association name. The documentation for the
`:recursive_on_duplicate_key_update` option specifies that the hash key is
the association name. But previously the name of associated table was used to
look up the options. Now the behavior matches the documentation and the name
of the association is used instead. This only affects associations that uses
a name that doesn't follow the ActiveRecord naming conventions of
associations and class names, i.e. when the `class_name:` option is used on
an association.

## Changes in 1.8.1

### Fixes
Expand Down
9 changes: 4 additions & 5 deletions lib/activerecord-import/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -859,12 +859,11 @@ def import_without_validations_or_callbacks( column_names, array_of_attributes,

private

def associated_options(options, associated_class)
def associated_options(options, association)
return options unless options.key?(:recursive_on_duplicate_key_update)

table_name = associated_class.arel_table.name.to_sym
options.merge(
on_duplicate_key_update: options[:recursive_on_duplicate_key_update][table_name]
on_duplicate_key_update: options[:recursive_on_duplicate_key_update][association]
)
end

Expand Down Expand Up @@ -973,12 +972,12 @@ def import_associations(models, options)
options.delete(:returning)

associated_objects_by_class.each_value do |associations|
associations.each_value do |associated_records|
associations.each do |association, associated_records|
next if associated_records.empty?

associated_class = associated_records.first.class
associated_class.bulk_import(associated_records,
associated_options(options, associated_class))
associated_options(options, association))
end
end
end
Expand Down
1 change: 1 addition & 0 deletions test/models/topic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Topic < ActiveRecord::Base
before_validation -> { errors.add(:title, :invalid) if title == 'invalid' }

has_many :books, inverse_of: :topic
has_many :novels, inverse_of: :topic, class_name: "Book"
belongs_to :parent, class_name: "Topic"

composed_of :description, mapping: [%w(title title), %w(author_name author_name)], allow_nil: true, class_name: "TopicDescription"
Expand Down
39 changes: 39 additions & 0 deletions test/support/shared_examples/recursive_import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,45 @@ def should_support_recursive_import
end
assert_equal new_chapter_title, Chapter.find(example_chapter.id).title
end

context "when a non-standard association name is used" do
let(:new_topics) do
topic = Build(:topic)

2.times do
novel = topic.novels.build(title: FactoryBot.generate(:book_title), author_name: 'Stephen King')
3.times do
novel.chapters.build(title: FactoryBot.generate(:chapter_title))
end

4.times do
novel.end_notes.build(note: FactoryBot.generate(:end_note))
end
end

[topic]
end

it "updates nested associated objects" do
new_chapter_title = 'The Final Chapter'
novel = new_topics.first.novels.first
novel.author_name = 'Richard Bachman'

example_chapter = novel.chapters.first
example_chapter.title = new_chapter_title

assert_nothing_raised do
Topic.import new_topics,
recursive: true,
on_duplicate_key_update: [:id],
recursive_on_duplicate_key_update: {
novels: { conflict_target: [:id], columns: [:author_name] },
chapters: { conflict_target: [:id], columns: [:title] }
}
end
assert_equal new_chapter_title, Chapter.find(example_chapter.id).title
end
end
end
end

Expand Down

0 comments on commit 2405beb

Please sign in to comment.