Skip to content

Commit

Permalink
Extract recursive import specs into a shared example
Browse files Browse the repository at this point in the history
  • Loading branch information
jkowens committed May 31, 2016
1 parent 2aa5f31 commit 1d25c94
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 119 deletions.
2 changes: 2 additions & 0 deletions test/sqlite3/import_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')

should_support_recursive_import

describe "#supports_imports?" do
context "and SQLite is 3.7.11 or higher" do
it "supports import" do
Expand Down
121 changes: 2 additions & 119 deletions test/support/postgresql/import_examples.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# encoding: UTF-8
def should_support_postgresql_import_functionality
should_support_recursive_import

describe "#supports_imports?" do
it "should support import" do
assert ActiveRecord::Base.supports_import?
Expand All @@ -18,112 +20,6 @@ def should_support_postgresql_import_functionality
end
end

describe "importing objects with associations" do
let(:new_topics) { Build(num_topics, :topic_with_book) }
let(:new_topics_with_invalid_chapter) do
chapter = new_topics.first.books.first.chapters.first
chapter.title = nil
new_topics
end
let(:num_topics) { 3 }
let(:num_books) { 6 }
let(:num_chapters) { 18 }
let(:num_endnotes) { 24 }

let(:new_question_with_rule) { FactoryGirl.build :question, :with_rule }

it 'imports top level' do
assert_difference "Topic.count", +num_topics do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
assert_not_nil topic.id
end
end
end

it 'imports first level associations' do
assert_difference "Book.count", +num_books do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
topic.books.each do |book|
assert_equal topic.id, book.topic_id
end
end
end
end

it 'imports polymorphic associations' do
discounts = Array.new(1) { |i| Discount.new(amount: i) }
books = Array.new(1) { |i| Book.new(author_name: "Author ##{i}", title: "Book ##{i}") }
books.each do |book|
book.discounts << discounts
end
Book.import books, recursive: true
books.each do |book|
book.discounts.each do |discount|
assert_not_nil discount.discountable_id
assert_equal 'Book', discount.discountable_type
end
end
end

[{ recursive: false }, {}].each do |import_options|
it "skips recursion for #{import_options}" do
assert_difference "Book.count", 0 do
Topic.import new_topics, import_options
end
end
end

it 'imports deeper nested associations' do
assert_difference "Chapter.count", +num_chapters do
assert_difference "EndNote.count", +num_endnotes do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
topic.books.each do |book|
book.chapters.each do |chapter|
assert_equal book.id, chapter.book_id
end
book.end_notes.each do |endnote|
assert_equal book.id, endnote.book_id
end
end
end
end
end
end

it "skips validation of the associations if requested" do
assert_difference "Chapter.count", +num_chapters do
Topic.import new_topics_with_invalid_chapter, validate: false, recursive: true
end
end

it 'imports has_one associations' do
assert_difference 'Rule.count' do
Question.import [new_question_with_rule], recursive: true
end
end

# These models dont validate associated. So we expect that books and topics get inserted, but not chapters
# Putting a transaction around everything wouldn't work, so if you want your chapters to prevent topics from
# being created, you would need to have validates_associated in your models and insert with validation
describe "all_or_none" do
[Book, Topic, EndNote].each do |type|
it "creates #{type}" do
assert_difference "#{type}.count", send("num_#{type.to_s.downcase}s") do
Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
end
end
end
it "doesn't create chapters" do
assert_difference "Chapter.count", 0 do
Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
end
end
end
end

describe "with query cache enabled" do
setup do
unless ActiveRecord::Base.connection.query_cache_enabled
Expand Down Expand Up @@ -294,19 +190,6 @@ def should_support_postgresql_upsert_functionality
should_update_updated_at_on_timestamp_columns
end
end

context "with recursive: true" do
let(:new_topics) { Build(1, :topic_with_book) }

it "imports objects with associations" do
assert_difference "Topic.count", +1 do
Topic.import new_topics, recursive: true, on_duplicate_key_update: [:updated_at], validate: false
new_topics.each do |topic|
assert_not_nil topic.id
end
end
end
end
end
end
end
122 changes: 122 additions & 0 deletions test/support/shared_examples/recursive_import.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
def should_support_recursive_import
describe "importing objects with associations" do
let(:new_topics) { Build(num_topics, :topic_with_book) }
let(:new_topics_with_invalid_chapter) do
chapter = new_topics.first.books.first.chapters.first
chapter.title = nil
new_topics
end
let(:num_topics) { 3 }
let(:num_books) { 6 }
let(:num_chapters) { 18 }
let(:num_endnotes) { 24 }

let(:new_question_with_rule) { FactoryGirl.build :question, :with_rule }

it 'imports top level' do
assert_difference "Topic.count", +num_topics do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
assert_not_nil topic.id
end
end
end

it 'imports first level associations' do
assert_difference "Book.count", +num_books do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
topic.books.each do |book|
assert_equal topic.id, book.topic_id
end
end
end
end

it 'imports polymorphic associations' do
discounts = Array.new(1) { |i| Discount.new(amount: i) }
books = Array.new(1) { |i| Book.new(author_name: "Author ##{i}", title: "Book ##{i}") }
books.each do |book|
book.discounts << discounts
end
Book.import books, recursive: true
books.each do |book|
book.discounts.each do |discount|
assert_not_nil discount.discountable_id
assert_equal 'Book', discount.discountable_type
end
end
end

[{ recursive: false }, {}].each do |import_options|
it "skips recursion for #{import_options}" do
assert_difference "Book.count", 0 do
Topic.import new_topics, import_options
end
end
end

it 'imports deeper nested associations' do
assert_difference "Chapter.count", +num_chapters do
assert_difference "EndNote.count", +num_endnotes do
Topic.import new_topics, recursive: true
new_topics.each do |topic|
topic.books.each do |book|
book.chapters.each do |chapter|
assert_equal book.id, chapter.book_id
end
book.end_notes.each do |endnote|
assert_equal book.id, endnote.book_id
end
end
end
end
end
end

it "skips validation of the associations if requested" do
assert_difference "Chapter.count", +num_chapters do
Topic.import new_topics_with_invalid_chapter, validate: false, recursive: true
end
end

it 'imports has_one associations' do
assert_difference 'Rule.count' do
Question.import [new_question_with_rule], recursive: true
end
end

# These models dont validate associated. So we expect that books and topics get inserted, but not chapters
# Putting a transaction around everything wouldn't work, so if you want your chapters to prevent topics from
# being created, you would need to have validates_associated in your models and insert with validation
describe "all_or_none" do
[Book, Topic, EndNote].each do |type|
it "creates #{type}" do
assert_difference "#{type}.count", send("num_#{type.to_s.downcase}s") do
Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
end
end
end
it "doesn't create chapters" do
assert_difference "Chapter.count", 0 do
Topic.import new_topics_with_invalid_chapter, all_or_none: true, recursive: true
end
end
end

# If adapter supports on_duplicate_key_update, it is only applied to top level models so that SQL with invalid
# columns, keys, etc isn't generated for child associations when doing recursive import
describe "on_duplicate_key_update" do
let(:new_topics) { Build(1, :topic_with_book) }

it "imports objects with associations" do
assert_difference "Topic.count", +1 do
Topic.import new_topics, recursive: true, on_duplicate_key_update: [:updated_at], validate: false
new_topics.each do |topic|
assert_not_nil topic.id
end
end
end
end
end
end

0 comments on commit 1d25c94

Please sign in to comment.