module ActiveRecord::Persistence::ClassMethods
Public Instance Methods
Creates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.
The attributes
parameter can be either a Hash or an Array of
Hashes. These Hashes describe the attributes on the objects that are to be
created.
Examples¶ ↑
# Create a single new object User.create(first_name: 'Jamie') # Create an Array of new objects User.create([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }]) # Create a single object and pass it into a block to set other attributes. User.create(first_name: 'Jamie') do |u| u.is_admin = false end # Creating an Array of new objects using a block, where the block is executed for each object: User.create([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }]) do |u| u.is_admin = false end
# File lib/active_record/persistence.rb, line 32 def create(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create(attr, &block) } else object = new(attributes, &block) object.save object end end
Creates an object (or multiple objects) and saves it to the database, if validations pass. Raises a RecordInvalid error if validations fail, unlike Base#create.
The attributes
parameter can be either a Hash or an Array of
Hashes. These describe which attributes to be created on the object, or
multiple objects when given an Array of Hashes.
# File lib/active_record/persistence.rb, line 49 def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } else object = new(attributes, &block) object.save! object end end
Deletes the row with a primary key matching the id
argument,
using an SQL DELETE
statement, and returns the number of rows
deleted. Active Record objects are not instantiated, so the object's
callbacks are not executed, including any :dependent
association options.
You can delete multiple rows at once by passing an Array of
id
s.
Note: Although it is often much faster than the alternative, destroy, skipping callbacks might bypass business logic in your application that ensures referential integrity or performs other essential jobs.
Examples¶ ↑
# Delete a single row Todo.delete(1) # Delete multiple rows Todo.delete([2,3,4])
# File lib/active_record/persistence.rb, line 350 def delete(id_or_array) delete_by(primary_key => id_or_array) end
Destroy an object (or multiple objects) that has the given id. The object is instantiated first, therefore all callbacks and filters are fired off before the object is deleted. This method is less efficient than delete but allows cleanup methods and other actions to be run.
This essentially finds the object (or multiple objects) with the given id, creates a new object from the attributes, and then calls destroy on it.
Parameters¶ ↑
-
id
- This should be the id or an array of ids to be destroyed.
Examples¶ ↑
# Destroy a single object Todo.destroy(1) # Destroy multiple objects todos = [1,2,3] Todo.destroy(todos)
# File lib/active_record/persistence.rb, line 324 def destroy(id) if id.is_a?(Array) find(id).each(&:destroy) else find(id).destroy end end
Inserts a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
See ActiveRecord::Persistence#insert_all
for documentation.
# File lib/active_record/persistence.rb, line 65 def insert(attributes, returning: nil, unique_by: nil) insert_all([ attributes ], returning: returning, unique_by: unique_by) end
Inserts a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
See ActiveRecord::Persistence#insert_all!
for more.
# File lib/active_record/persistence.rb, line 132 def insert!(attributes, returning: nil) insert_all!([ attributes ], returning: returning) end
Inserts multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
The attributes
parameter is an Array of Hashes. Every Hash
determines the attributes for a single row and must have the same keys.
Rows are considered to be unique by every unique index on the table. Any
duplicate rows are skipped. Override with :unique_by
(see
below).
Returns an ActiveRecord::Result
with its contents based on
:returning
(see below).
Options¶ ↑
- :returning
-
(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass
returning: %w[ id name ]
for both id and name orreturning: false
to omit the underlyingRETURNING
SQL clause entirely. - :unique_by
-
(PostgreSQL and SQLite only) By default rows are considered to be unique by every unique index on the table. Any duplicate rows are skipped.
To skip rows according to just one unique index pass
:unique_by
.Consider a Book model where no duplicate ISBNs make sense, but if any row has an existing id, or is not unique by another unique index,
ActiveRecord::RecordNotUnique
is raised.Unique indexes can be identified by columns or name:
unique_by: :isbn unique_by: %i[ author_id name ] unique_by: :index_books_on_isbn
Because it relies on the index information from the database
:unique_by
is recommended to be paired with Active
Record's schema_cache.
Example¶ ↑
# Insert records and skip inserting any duplicates. # Here "Eloquent Ruby" is skipped because its id is not unique. Book.insert_all([ { id: 1, title: "Rework", author: "David" }, { id: 1, title: "Eloquent Ruby", author: "Russ" } ])
# File lib/active_record/persistence.rb, line 122 def insert_all(attributes, returning: nil, unique_by: nil) InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by).execute end
Inserts multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
The attributes
parameter is an Array of Hashes. Every Hash
determines the attributes for a single row and must have the same keys.
Raises ActiveRecord::RecordNotUnique
if any rows violate a
unique index on the table. In that case, no rows are inserted.
To skip duplicate rows, see
ActiveRecord::Persistence#insert_all
. To replace them, see
ActiveRecord::Persistence#upsert_all
.
Returns an ActiveRecord::Result
with its contents based on
:returning
(see below).
Options¶ ↑
- :returning
-
(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass
returning: %w[ id name ]
for both id and name orreturning: false
to omit the underlyingRETURNING
SQL clause entirely.
Examples¶ ↑
# Insert multiple records Book.insert_all!([ { title: "Rework", author: "David" }, { title: "Eloquent Ruby", author: "Russ" } ]) # Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby" # does not have a unique id. Book.insert_all!([ { id: 1, title: "Rework", author: "David" }, { id: 1, title: "Eloquent Ruby", author: "Russ" } ])
# File lib/active_record/persistence.rb, line 176 def insert_all!(attributes, returning: nil) InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning).execute end
Given an attributes hash, instantiate
returns a new instance
of the appropriate class. Accepts only keys as strings.
For example, Post.all
may return Comments, Messages, and
Emails by storing the record's subclass in a type
attribute. By calling instantiate
instead of new
,
finder methods ensure they get new instances of the appropriate class for
each record.
See ActiveRecord::Inheritance#discriminate_class_for_record
to
see how this “single-table” inheritance mapping is implemented.
# File lib/active_record/persistence.rb, line 255 def instantiate(attributes, column_types = {}, &block) klass = discriminate_class_for_record(attributes) instantiate_instance_of(klass, attributes, column_types, &block) end
Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.
Parameters¶ ↑
-
id
- This should be the id or an array of ids to be updated. -
attributes
- This should be a hash of attributes or an array of hashes.
Examples¶ ↑
# Updates one record Person.update(15, user_name: "Samuel", group: "expert") # Updates multiple records people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } } Person.update(people.keys, people.values) # Updates multiple records from the result of a relation people = Person.where(group: "expert") people.update(group: "masters")
Note: Updating a large number of records will run an UPDATE query for each record, which may cause a performance issue. When running callbacks is not needed for each record update, it is preferred to use update_all for updating all records in a single query.
# File lib/active_record/persistence.rb, line 286 def update(id = :all, attributes) if id.is_a?(Array) id.map { |one_id| find(one_id) }.each_with_index { |object, idx| object.update(attributes[idx]) } elsif id == :all all.each { |record| record.update(attributes) } else if ActiveRecord::Base === id raise ArgumentError, "You are passing an instance of ActiveRecord::Base to `update`. " \ "Please pass the id of the object by calling `.id`." end object = find(id) object.update(attributes) object end end
Updates or inserts (upserts) a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
See ActiveRecord::Persistence#upsert_all
for documentation.
# File lib/active_record/persistence.rb, line 186 def upsert(attributes, returning: nil, unique_by: nil) upsert_all([ attributes ], returning: returning, unique_by: unique_by) end
Updates or inserts (upserts) multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record's type casting and serialization.
The attributes
parameter is an Array of Hashes. Every Hash
determines the attributes for a single row and must have the same keys.
Returns an ActiveRecord::Result
with its contents based on
:returning
(see below).
Options¶ ↑
- :returning
-
(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass
returning: %w[ id name ]
for both id and name orreturning: false
to omit the underlyingRETURNING
SQL clause entirely. - :unique_by
-
(PostgreSQL and SQLite only) By default rows are considered to be unique by every unique index on the table. Any duplicate rows are skipped.
To skip rows according to just one unique index pass
:unique_by
.Consider a Book model where no duplicate ISBNs make sense, but if any row has an existing id, or is not unique by another unique index,
ActiveRecord::RecordNotUnique
is raised.Unique indexes can be identified by columns or name:
unique_by: :isbn unique_by: %i[ author_id name ] unique_by: :index_books_on_isbn
Because it relies on the index information from the database
:unique_by
is recommended to be paired with Active
Record's schema_cache.
Examples¶ ↑
# Inserts multiple records, performing an upsert when records have duplicate ISBNs. # Here "Eloquent Ruby" overwrites "Rework" because its ISBN is duplicate. Book.upsert_all([ { title: "Rework", author: "David", isbn: "1" }, { title: "Eloquent Ruby", author: "Russ", isbn: "1" } ], unique_by: :isbn) Book.find_by(isbn: "1").title # => "Eloquent Ruby"
# File lib/active_record/persistence.rb, line 241 def upsert_all(attributes, returning: nil, unique_by: nil) InsertAll.new(self, attributes, on_duplicate: :update, returning: returning, unique_by: unique_by).execute end
Private Instance Methods
# File lib/active_record/persistence.rb, line 414 def _substitute_values(values) values.map do |name, value| attr = arel_attribute(name) bind = predicate_builder.build_bind_attribute(name, value) [attr, bind] end end
Called by instantiate
to decide which class to use for a new
record instance.
See +ActiveRecord::Inheritance#discriminate_class_for_record+ for the single-table inheritance discriminator.
# File lib/active_record/persistence.rb, line 410 def discriminate_class_for_record(record) self end
Given a class, an attributes hash, instantiate_instance_of
returns a new instance of the class. Accepts only keys as strings.
# File lib/active_record/persistence.rb, line 400 def instantiate_instance_of(klass, attributes, column_types = {}, &block) attributes = klass.attributes_builder.build_from_database(attributes, column_types) klass.allocate.init_with_attributes(attributes, &block) end