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
5 changes: 3 additions & 2 deletions lib/active_admin_import/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
module ActiveAdminImport
class Importer

attr_reader :resource, :options, :result, :headers, :csv_lines, :model
attr_reader :resource, :options, :result, :model
attr_accessor :csv_lines, :headers

OPTIONS = [
:validate,
Expand Down Expand Up @@ -85,7 +86,7 @@ def process_file
end

def prepare_headers
headers = self.headers.present? ? self.headers : yield
headers = self.headers.present? ? self.headers.map(&:to_s) : yield
@headers = Hash[headers.zip(headers.map { |el| el.underscore.gsub(/\s+/, '_') })].with_indifferent_access
@headers.merge!(options[:headers_rewrites].symbolize_keys.slice(*@headers.symbolize_keys.keys))
@headers
Expand Down
3 changes: 3 additions & 0 deletions spec/fixtures/files/posts_for_author.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"Title","Body"
"title1","some body"
"title2","some body"
2 changes: 2 additions & 0 deletions spec/fixtures/files/posts_for_author_no_headers.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"title1","some body"
"title2","some body"
149 changes: 84 additions & 65 deletions spec/import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
expect(author.last_name).to be_present
end
end

end

def with_zipped_csv(name, &block)
Expand All @@ -36,7 +35,6 @@ def with_zipped_csv(name, &block)
ensure
File.delete zip_file rescue nil
end

end

def upload_file!(name, ext='csv')
Expand All @@ -48,35 +46,85 @@ def upload_file!(name, ext='csv')
before do
Author.create!(name: "John", last_name: "Doe")
Author.create!(name: "Jane", last_name: "Roe")
add_post_resource({
validate: true,
headers_rewrites: {
:'Author Name' => :author_id
},
before_batch_import: ->(importer) do
authors_names = importer.values_at(:author_id)
# replacing author name with author id
authors = Author.where(name: authors_names).pluck(:name, :id)
#{"Jane" => 2, "John" => 1}
options = Hash[*authors.flatten]
importer.batch_replace(:author_id, options)
end
})
visit "/admin/posts/import"
upload_file!(:posts)
end

it "should resolve author_id by author name" do
Post.all.each do |post|
expect(Author.where(id: post.author.id)).to be_present
context "for csv for particular author" do
let(:author) { Author.take }

shared_examples 'successful inserts for author' do
it "should use predefined author_id" do
expect(Post.where(author_id: author.id).count).to eq(Post.count)
end

it "should be imported" do
expect(Post.count).to eq(2)
expect(page).to have_content "Successfully imported 2 posts"
end
end

context "no headers" do
before do
add_post_resource(template_object: ActiveAdminImport::Model.new(author_id: author.id,

Choose a reason for hiding this comment

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

Line is too long. [95/80]

csv_headers: [:title, :body, :author_id]),

Choose a reason for hiding this comment

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

Line is too long. [116/80]

validate: true,
before_batch_import: ->(importer) do
importer.csv_lines.map! { |row| row << importer.model.author_id }

Choose a reason for hiding this comment

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

Line is too long. [95/80]

end
)

visit "/admin/posts/import"
upload_file!(:posts_for_author_no_headers)
end
include_examples 'successful inserts for author'
end
end

it "should be imported" do
expect(Post.count).to eq(2)
expect(page).to have_content "Successfully imported 2 posts"
context "with headers" do
before do
add_post_resource(template_object: ActiveAdminImport::Model.new(author_id: author.id),

Choose a reason for hiding this comment

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

Line is too long. [96/80]

validate: true,
before_batch_import: ->(importer) do
importer.csv_lines.map! { |row| row << importer.model.author_id }

Choose a reason for hiding this comment

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

Line is too long. [95/80]

importer.headers.merge!({ :'Author Id' => :author_id })

Choose a reason for hiding this comment

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

Line is too long. [85/80]
Redundant curly braces around a hash parameter.

end
)

visit "/admin/posts/import"
upload_file!(:posts_for_author)
end
include_examples 'successful inserts for author'
end
end

context "for csv with author name" do
before do
add_post_resource(
validate: true,

Choose a reason for hiding this comment

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

Indent the first parameter one step more than the previous line.

template_object: ActiveAdminImport::Model.new,
headers_rewrites: { :'Author Name' => :author_id },
before_batch_import: ->(importer) do
authors_names = importer.values_at(:author_id)
# replacing author name with author id
authors = Author.where(name: authors_names).pluck(:name, :id)
#{"Jane" => 2, "John" => 1}

Choose a reason for hiding this comment

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

Missing space after #.

options = Hash[*authors.flatten]
importer.batch_replace(:author_id, options)
end
)
visit "/admin/posts/import"
upload_file!(:posts)
end

it "should resolve author_id by author name" do
Post.all.each do |post|
expect(Author.where(id: post.author.id)).to be_present
end
end

it "should be imported" do
expect(Post.count).to eq(2)
expect(page).to have_content "Successfully imported 2 posts"
end
end
end

context "authors index" do
Expand All @@ -91,27 +139,21 @@ def upload_file!(name, ext='csv')
find_link('Import Authors').click
expect(current_path).to eq("/admin/authors/import")
end


end

context "with custom block" do


before do
add_author_resource({}) do
flash[:notice] = 'some custom message'
end
visit '/admin/authors/import'

end

it "should display notice from custom block" do
upload_file!(:author)
expect(page).to have_content "some custom message"
end


end

context "authors already exist" do
Expand All @@ -122,11 +164,11 @@ def upload_file!(name, ext='csv')

context "having authors with the same Id" do
before do
add_author_resource({
before_batch_import: ->(importer) do
Author.where(id: importer.values_at("id")).delete_all
end
})
add_author_resource(
before_batch_import: ->(importer) do

Choose a reason for hiding this comment

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

Indent the first parameter one step more than the previous line.

Author.where(id: importer.values_at("id")).delete_all
end
)
visit "/admin/authors/import"
upload_file!(:authors_with_ids)
end
Expand All @@ -136,13 +178,11 @@ def upload_file!(name, ext='csv')
expect(Author.count).to eq(2)
end

it "should replace authors by id" do
it "should replace authors by id" do
expect(Author.find(1).name).to eq("John")
expect(Author.find(2).name).to eq("Jane")
end

end

end

context "with valid options" do
Expand All @@ -154,7 +194,6 @@ def upload_file!(name, ext='csv')
visit '/admin/authors/import'
end


it "has valid form" do
form = find('#new_active_admin_import_model')
expect(form['action']).to eq("/admin/authors/do_import")
Expand Down Expand Up @@ -209,17 +248,14 @@ def upload_file!(name, ext='csv')
end

context "BOM" do

it "should import file with many records" do
upload_file!(:authors_bom)
expect(page).to have_content "Successfully imported 2 authors"
expect(Author.count).to eq(2)
end

end

context "with headers" do

it "should import file with many records" do
upload_file!(:authors)
expect(page).to have_content "Successfully imported 2 authors"
Expand All @@ -231,13 +267,10 @@ def upload_file!(name, ext='csv')
expect(page).to have_content "Successfully imported 1 author"
expect(Author.count).to eq(1)
end

end


context "without headers" do
context "with known csv headers" do

let(:options) do
attributes = { csv_headers: ['Name', 'Last name', 'Birthday'] }
{ template_object: ActiveAdminImport::Model.new(attributes) }
Expand All @@ -248,7 +281,6 @@ def upload_file!(name, ext='csv')
expect(page).to have_content "Successfully imported 2 authors"
expect(Author.count).to eq(2)
end

end

context "with unknown csv headers" do
Expand All @@ -269,7 +301,6 @@ def upload_file!(name, ext='csv')
end

context "with invalid records" do

context "with validation" do
it "should render error" do
upload_file!(:author_invalid)
Expand All @@ -278,31 +309,25 @@ def upload_file!(name, ext='csv')
end
end


context "without validation" do
let(:options) { { validate: false } }
it "should render error" do
upload_file!(:author_invalid)
expect(page).to have_content "Successfully imported 1 author"
expect(Author.count).to eq(1)
end

end


end

context "when zipped" do
context "when allowed" do

it "should import file" do
with_zipped_csv(:authors) do
upload_file!(:authors, :zip)
expect(page).to have_content "Successfully imported 2 authors"
expect(Author.count).to eq(2)
end
end

end

context "when not allowed" do
Expand All @@ -321,9 +346,8 @@ def upload_file!(name, ext='csv')
end

context "with different header attribute names" do

let(:options) do
{ headers_rewrites: {:'Second name' => :last_name} }
{ headers_rewrites: { :'Second name' => :last_name } }
end

it "should import file" do
Expand All @@ -334,7 +358,6 @@ def upload_file!(name, ext='csv')
end

context "with semicolons separator" do

let(:options) do
attributes = { csv_options: { col_sep: ";" } }
{ template_object: ActiveAdminImport::Model.new(attributes) }
Expand All @@ -346,21 +369,18 @@ def upload_file!(name, ext='csv')
expect(Author.count).to eq(2)
end
end

end


context "with callback procs options" do
let(:options) do
{
before_import: ->(_) { true },
after_import: ->(_) { true },
before_batch_import: ->(_) { true },
after_batch_import: ->(_) { true }
before_import: ->(_) { true },

Choose a reason for hiding this comment

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

Use 2 spaces for indentation in a hash, relative to the start of the line where the left curly brace is.

after_import: ->(_) { true },
before_batch_import: ->(_) { true },
after_batch_import: ->(_) { true }
}
end


it "should call each callback" do
expect(options[:before_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
expect(options[:after_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
Expand All @@ -382,5 +402,4 @@ def upload_file!(name, ext='csv')

end


end