class ActiveRecord::Base
def import(*args)
* num_inserts - the number of insert statements it took to import the data
* failed_instances - an array of objects that fails validation and were not committed to the database. An empty array if no validation is performed.
This returns an object which responds to +failed_instances+ and +num_inserts+.
= Returns
BlogPost.import columns, attributes, on_duplicate_key_update: { conflict_target: :slug, columns: { title: :title } }
with what attributes on your model. Below is an example:
mappings. This gives you finer grained control over what fields are updated
The :columns option can be a hash of column names to model attribute name
======== Using a Hash
BlogPost.import columns, values, on_duplicate_key_update: { conflict_target: :slug, columns: [ :date_modified, :content, :author ] }
Below is an example:
are the only fields that are updated if a duplicate record is found.
The :columns attribute can be an array of column names. The column names
======== Using an Array
The :columns attribute can be either an Array or a Hash.
====== :columns
BlogPost.import columns, values, on_duplicate_key_update: { constraint_name: :blog_posts_pkey, columns: [ :date_modified ] }
of identifying an index unless absolutely necessary. Below is an example:
unique index by name. Postgres documentation discourages using this method
The :constraint_name attribute explicitly identifies the conflicting
====== :constraint_name
BlogPost.import columns, values, on_duplicate_key_update: { conflict_target: [ :author_id, :slug ], index_predicate: 'status <> 0', columns: [ :date_modified ] }
Below is an example:
indexes. This attribute is ignored if :constraint_name is included.
on :conflict_target, which is required for matching against partial
The :index_predicate attribute optionally specifies a WHERE condition
====== :index_predicate
BlogPost.import columns, values, on_duplicate_key_update: { conflict_target: [ :author_id, :slug ], columns: [ :date_modified ] }
default to the primary key. Below is an example:
but it is the preferred method of identifying a constraint. It will
column names. This attribute is ignored if :constraint_name is included,
conflicting unique constraint and can be a single column or an array of
The :conflict_target attribute specifies the columns that make up the
====== :conflict_target
allows you to specify a constraint other than the primary key.
conflicting constraint to be explicitly specified. Using this option
:constraint_name, and :columns. Unlike MySQL, Postgres requires the
attributes, :conflict_target (and optionally :index_predicate) or
The :on_duplicate_key_update option can be a hash with up to three
==== Using a Hash
BlogPost.import columns, values, on_duplicate_key_update: [ :date_modified, :content, :author ]
if a duplicate record is found. Below is an example:
not work. The column names are the only fields that are updated
primary key. If a table does not have a primary key, this will
names. This option only handles inserts that conflict with the
The :on_duplicate_key_update option can be an array of column
==== Using an Array
:constraint_name, and :columns.
three attributes, :conflict_target (and optionally :index_predicate) or
The :on_duplicate_key_update option can be an Array or a Hash with up to
== On Duplicate Key Update (Postgres 9.5+)
BlogPost.import columns, attributes, on_duplicate_key_update: { title: :title }
model. Below is an example:
control over what fields are updated with what attributes on your
to model attribute name mappings. This gives you finer grained
The :on_duplicate_key_update option can be a hash of column names
==== Using A Hash
BlogPost.import columns, values, on_duplicate_key_update: [ :date_modified, :content, :author ]
a duplicate record is found. Below is an example:
names. The column names are the only fields that are updated if
The :on_duplicate_key_update option can be an array of column
==== Using an Array
The :on_duplicate_key_update option can be either an Array or a Hash.
== On Duplicate Key Update (MySQL)
puts posts.first.persisted? # => true
BlogPost.import posts, synchronize: posts, synchronize_keys: [:title]
posts = [BlogPost.new(title: "Foo"), BlogPost.new(title: "Bar")]
# Example synchronizing unsaved/new instances in memory by using a uniqued imported field
puts post.author_name # => 'yoda'
BlogPost.import posts, synchronize: [ post ]
values = [ [ 'yoda', 'test post' ] ]
columns = [ :author_name, :title ]
puts post.author_name # => 'zdennis'
post = BlogPost.where(author_name: 'zdennis').first
# Example synchronizing existing instances in memory
BlogPost.import( columns, values, validate: false )
values = [ [ 'zdennis', 'test post' ], [ 'jdoe', 'another test post' ] ]
columns = [ :author_name, :title ]
# Example using column_names, array_of_value and options
BlogPost.import columns, values
values = [ [ 'zdennis', 'test post' ], [ 'jdoe', 'another test post' ] ]
columns = [ :author_name, :title ]
# Example using column_names and array_of_values
BlogPost.import columns, values
values = [ {author_name: 'zdennis', title: 'test post'} ], [ {author_name: 'jdoe', title: 'another test post'} ] ]
columns = [ :author_name, :title ]
# Example using column_names and array_of_hash_objects
BlogPost.import values
values = [ {author_name: 'zdennis', title: 'test post'} ], [ {author_name: 'jdoe', title: 'another test post'} ] ]
# Example using array_of_hash_objects
BlogPost.import posts
BlogPost.new author_name: 'Zach Dennis', title: 'AREXT3' ]
BlogPost.new author_name: 'Zach Dennis', title: 'AREXT2',
posts = [ BlogPost.new author_name: 'Zach Dennis', title: 'AREXT',
# Example using array of model objects
class BlogPost < ActiveRecord::Base ; end
== Examples
include per insert. Defaults to the total number of records to import.
* +batch_size+ - an integer value to specify the max number of records to
newly imported objects. PostgreSQL only.
associations if the adapter supports setting the primary keys of the
* +recursive+ - true|false, tells import to import all has_many/has_one
(if false) even if record timestamps is disabled in ActiveRecord::Base
* +timestamps+ - true|false, tells import to not add timestamps
existing model instances in memory with updates from the import.
that you are currently importing data into. This synchronizes
* +synchronize+ - an array of ActiveRecord instances for the model
DO UPDATE ability. See On Duplicate Key Update below.
use MySQL's ON DUPLICATE KEY UPDATE or Postgres 9.5+ ON CONFLICT
* +on_duplicate_key_update+ - an Array or Hash, tells import to
recursive import.
SQLite it uses INSERT OR IGNORE. Cannot be enabled on a
ON CONFLICT DO NOTHING, for MySQL it uses INSERT IGNORE, and for
records that contain duplicate keys. For Postgres 9.5+ it adds
* +on_duplicate_key_ignore+ - true|false, tells import to discard
* +ignore+ - true|false, an alias for on_duplicate_key_ignore.
ActiveRecord validations. Validations are enforced by default.
* +validate+ - true|false, tells import whether or not to use
== Options
below for what +options+ are available.
parameter, +options+, is a hash. This is optional. Please see
The first two parameters are the same as the above form. The third
==== Model.import column_names, array_of_values, options
the order of the +column_names+.
record. The order of values in each subarray should match up to
arrays. Each subarray is a single set of values for a new
The second parameter, +array_of_values+, is an array of
strings which specify the columns that you want to update.
The first parameter +column_names+ is an array of symbols or
==== Model.import column_names, array_of_values
objects that you want updated.
With this form you can call _import_ passing in an array of model
==== Model.import array_of_models
Model.import column_names, array_of_values, options
Model.import column_names, array_of_values
Model.import column_names, array_of_hash_objects
Model.import array_of_hash_objects
Model.import column_names, array_of_models
Model.import array_of_models
== Usage
performing the import.
the ActiveRecord::Callbacks during creation/modification while
This can be used with or without validations. It does not utilize
inserted.
about having ActiveRecord objects returned for each record
you want to create more than one record at a time and do not care
ActiveRecord::Base#save multiple times. This method works well if
This is more efficient than using ActiveRecord::Base#create or
Imports a collection of values to the database.
def import(*args) if args.first.is_a?( Array ) && args.first.first.is_a?(ActiveRecord::Base) options = {} options.merge!( args.pop ) if args.last.is_a?(Hash) models = args.first import_helper(models, options) else import_helper(*args) end end