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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Tool | Description
:timestamps |bool, tells activerecord-import to not add timestamps (if false) even if record timestamps is disabled in ActiveRecord::Base
:template |custom template rendering
:template_object |object passing to view
:result_class |custom `ImportResult` subclass to collect data from each batch (e.g. inserted ids). Must respond to `add(batch_result, qty)` plus the readers used in flash messages (`failed`, `total`, `imported_qty`, `imported?`, `failed?`, `empty?`, `failed_message`).
:resource_class |resource class name
:resource_label |resource label value
:plural_resource_label |pluralized resource label value (default config.plural_resource_label)
Expand All @@ -77,6 +78,37 @@ Tool | Description



#### Custom ImportResult

To collect extra data from each batch (for example the ids of inserted rows so you can enqueue background jobs against them), pass a subclass of `ActiveAdminImport::ImportResult` via `:result_class`:

```ruby
class ImportResultWithIds < ActiveAdminImport::ImportResult
attr_reader :ids

def initialize
super
@ids = []
end

def add(batch_result, qty)
super
@ids.concat(Array(batch_result.ids))
end
end

ActiveAdmin.register Author do
active_admin_import result_class: ImportResultWithIds do |result, options|
EnqueueAuthorsJob.perform_later(result.ids) if result.imported?
instance_exec(result, options, &ActiveAdminImport::DSL::DEFAULT_RESULT_PROC)
end
end
```

The action block is invoked via `instance_exec` with `result` and `options` as block arguments, so you can either capture them with `do |result, options|` or read them as locals when no arguments are declared.

Note: which batch-result attributes are populated depends on the database adapter and the import options. `activerecord-import` returns ids reliably on PostgreSQL; on MySQL/SQLite the behavior depends on the adapter and options like `on_duplicate_key_update`. Putting the collection logic in your own subclass keeps these adapter quirks in your application code.

#### Wiki

[Check various examples](https://github.com/activeadmin-plugins/active_admin_import/wiki)
Expand Down
2 changes: 1 addition & 1 deletion lib/active_admin_import/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def active_admin_import(options = {}, &block)
result = @importer.import

if block_given?
instance_eval(&block)
instance_exec result, options, &block
else
instance_exec result, options, &DEFAULT_RESULT_PROC
end
Expand Down
5 changes: 3 additions & 2 deletions lib/active_admin_import/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class Importer
:headers_rewrites,
:batch_size,
:batch_transaction,
:csv_options
:csv_options,
:result_class
].freeze

def initialize(resource, model, options)
Expand All @@ -29,7 +30,7 @@ def initialize(resource, model, options)
end

def import_result
@import_result ||= ImportResult.new
@import_result ||= (options[:result_class] || ImportResult).new
end

def file
Expand Down
1 change: 1 addition & 0 deletions lib/active_admin_import/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module Options
:ignore,
:template,
:template_object,
:result_class,
:resource_class,
:resource_label,
:plural_resource_label,
Expand Down
42 changes: 42 additions & 0 deletions spec/import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -689,4 +689,46 @@ def active_admin_import_context
end
end
end

# PG-only: activerecord-import populates `result.ids` reliably on PostgreSQL
# via RETURNING. On MySQL/SQLite the array is not populated by default, so
# the assertion would not be meaningful there. The :result_class option
# itself works on every adapter — this spec just demonstrates the canonical
# PR #191 use case (collecting inserted ids) on the adapter that supports it.
if ENV['DB'] == 'postgres'
context 'with custom result_class (PostgreSQL)' do
# Subclass that captures inserted ids alongside the standard counters.
# Lives in user-land so the gem itself stays free of adapter-specific
# quirks around RETURNING. This is the example documented in the README.
class ImportResultWithIds < ActiveAdminImport::ImportResult
attr_reader :ids

def initialize
super
@ids = []
end

def add(batch_result, qty)
super
@ids.concat(Array(batch_result.ids))
end
end

before do
add_author_resource(result_class: ImportResultWithIds) do |result, _options|
# Expose the captured ids on the flash so the test asserts via the
# rendered page rather than closure capture.
flash[:notice] = "Imported ids: [#{result.ids.sort.join(',')}]"
end
visit '/admin/authors/import'
upload_file!(:authors)
end

it 'collects the ids of inserted records via the custom subclass' do
expect(Author.count).to eq(2)
expected = "Imported ids: [#{Author.pluck(:id).sort.join(',')}]"
expect(page).to have_content(expected)
end
end
end
end
Loading