Module: ActiveRecord::Persistence::ClassMethods
Relationships & Source Files | |
Defined in: | activerecord/lib/active_record/persistence.rb |
Instance Attribute Summary
- #has_query_constraints? ⇒ Boolean readonly Internal use only
Instance Method Summary
-
#build(attributes = nil, &block)
Builds an object (or multiple objects) and returns either the built object or a list of built objects.
-
#create(attributes = nil, &block)
Creates an object (or multiple objects) and saves it to the database, if validations pass.
-
#create!(attributes = nil, &block)
Creates an object (or multiple objects) and saves it to the database, if validations pass.
-
#instantiate(attributes, column_types = {}, &block)
Given an attributes hash, #instantiate returns a new instance of the appropriate class.
-
#query_constraints(*columns_list)
Accepts a list of attribute names to be used in the WHERE clause of SELECT / UPDATE / DELETE queries and in the ORDER BY clause for
#first
and#last
finder methods. -
#update(id = :all, attributes)
Updates an object (or multiple objects) and saves it to the database, if validations pass.
- #update!(id = :all, attributes)
-
#build_default_constraint
private
Called by #_update_record and #_delete_record to build
where
clause from default scopes. -
#discriminate_class_for_record(record)
private
Called by #instantiate to decide which class to use for a new record instance.
- #inherited(subclass) private
-
#instantiate_instance_of(klass, attributes, column_types = {}, &block)
private
Given a class, an attributes hash, #instantiate_instance_of returns a new instance of the class.
- #_delete_record(constraints) Internal use only
- #_insert_record(connection, values, returning) Internal use only
- #_update_record(values, constraints) Internal use only
-
#composite_query_constraints_list
Internal use only
Returns an array of column names to be used in queries.
- #query_constraints_list Internal use only
Instance Attribute Details
#has_query_constraints? ⇒ Boolean
(readonly)
# File 'activerecord/lib/active_record/persistence.rb', line 219
def has_query_constraints? # :nodoc: @has_query_constraints end
Instance Method Details
#_delete_record(constraints)
# File 'activerecord/lib/active_record/persistence.rb', line 282
def _delete_record(constraints) # :nodoc: constraints = constraints.map { |name, value| predicate_builder[name, value] } default_constraint = build_default_constraint constraints << default_constraint if default_constraint if current_scope = self.global_current_scope constraints << current_scope.where_clause.ast end dm = Arel::DeleteManager.new(arel_table) dm.wheres = constraints with_connection do |c| c.delete(dm, "#{self} Destroy") end end
#_insert_record(connection, values, returning)
# File 'activerecord/lib/active_record/persistence.rb', line 238
def _insert_record(connection, values, returning) # :nodoc: primary_key = self.primary_key primary_key_value = nil if prefetch_primary_key? && primary_key values[primary_key] ||= begin primary_key_value = next_sequence_value _default_attributes[primary_key].with_cast_value(primary_key_value) end end im = Arel::InsertManager.new(arel_table) if values.empty? im.insert(connection.empty_insert_statement_value(primary_key)) else im.insert(values.transform_keys { |name| arel_table[name] }) end connection.insert( im, "#{self} Create", primary_key || false, primary_key_value, returning: returning ) end
#_update_record(values, constraints)
# File 'activerecord/lib/active_record/persistence.rb', line 263
def _update_record(values, constraints) # :nodoc: constraints = constraints.map { |name, value| predicate_builder[name, value] } default_constraint = build_default_constraint constraints << default_constraint if default_constraint if current_scope = self.global_current_scope constraints << current_scope.where_clause.ast end um = Arel::UpdateManager.new(arel_table) um.set(values.transform_keys { |name| arel_table[name] }) um.wheres = constraints with_connection do |c| c.update(um, "#{self} Update") end end
#build(attributes = nil, &block)
Builds an object (or multiple objects) and returns either the built object or a list of built objects.
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 built.
Examples
# Build a single new object
User.build(first_name: 'Jamie')
# Build an Array of new objects
User.build([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }])
# Build a single object and pass it into a block to set other attributes.
User.build(first_name: 'Jamie') do |u|
u.is_admin = false
end
# Building an Array of new objects using a block, where the block is executed for each object:
User.build([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }]) do |u|
u.is_admin = false
end
# File 'activerecord/lib/active_record/persistence.rb', line 82
def build(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| build(attr, &block) } else new(attributes, &block) end end
#build_default_constraint (private)
Called by #_update_record and #_delete_record to build where
clause from default scopes. Skips empty scopes.
# File 'activerecord/lib/active_record/persistence.rb', line 328
def build_default_constraint return unless default_scopes?(all_queries: true) default_where_clause = default_scoped(all_queries: true).where_clause default_where_clause.ast unless default_where_clause.empty? end
#composite_query_constraints_list
Returns an array of column names to be used in queries. The source of column names is derived from #query_constraints_list or primary_key
. This method is for internal use when the primary key is to be treated as an array.
# File 'activerecord/lib/active_record/persistence.rb', line 234
def composite_query_constraints_list # :nodoc: @composite_query_constraints_list ||= query_constraints_list || Array(primary_key) end
#create(attributes = nil, &block)
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
#create!(attributes = nil, &block)
Creates an object (or multiple objects) and saves it to the database, if validations pass. Raises a ::ActiveRecord::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.
#discriminate_class_for_record(record) (private)
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 'activerecord/lib/active_record/persistence.rb', line 321
def discriminate_class_for_record(record) self end
#inherited(subclass) (private)
[ GitHub ]# File 'activerecord/lib/active_record/persistence.rb', line 301
def inherited(subclass) super subclass.class_eval do @_query_constraints_list = nil @has_query_constraints = false end end
#instantiate(attributes, column_types = {}, &block)
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 'activerecord/lib/active_record/persistence.rb', line 100
def instantiate(attributes, column_types = {}, &block) klass = discriminate_class_for_record(attributes) instantiate_instance_of(klass, attributes, column_types, &block) end
#instantiate_instance_of(klass, attributes, column_types = {}, &block) (private)
Given a class, an attributes hash, instantiate_instance_of
returns a new instance of the class. Accepts only keys as strings.
# File 'activerecord/lib/active_record/persistence.rb', line 311
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
#query_constraints(*columns_list)
Accepts a list of attribute names to be used in the WHERE clause of SELECT / UPDATE / DELETE queries and in the ORDER BY clause for #first
and #last
finder methods.
class Developer < ActiveRecord::Base
query_constraints :company_id, :id
end
developer = Developer.first
# SELECT "developers".* FROM "developers" ORDER BY "developers"."company_id" ASC, "developers"."id" ASC LIMIT 1
developer.inspect # => #<Developer id: 1, company_id: 1, ...>
developer.update!(name: "Nikita")
# UPDATE "developers" SET "name" = 'Nikita' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
# It is possible to update an attribute used in the query_constraints clause:
developer.update!(company_id: 2)
# UPDATE "developers" SET "company_id" = 2 WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
developer.name = "Bob"
developer.save!
# UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
developer.destroy!
# DELETE FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
developer.delete
# DELETE FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
developer.reload
# SELECT "developers".* FROM "developers" WHERE "developers"."company_id" = 1 AND "developers"."id" = 1 LIMIT 1
# File 'activerecord/lib/active_record/persistence.rb', line 212
def query_constraints(*columns_list) raise ArgumentError, "You must specify at least one column to be used in querying" if columns_list.empty? @query_constraints_list = columns_list.map(&:to_s) @has_query_constraints = @query_constraints_list end
#query_constraints_list
# File 'activerecord/lib/active_record/persistence.rb', line 223
def query_constraints_list # :nodoc: @query_constraints_list ||= if base_class? || primary_key != base_class.primary_key primary_key if primary_key.is_a?(Array) else base_class.query_constraints_list end end
#update(id = :all, attributes)
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. Optional argument, defaults to all records in the relation. -
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 'activerecord/lib/active_record/persistence.rb', line 132
def update(id = :all, attributes) if id.is_a?(Array) if id.any?(ActiveRecord::Base) raise ArgumentError, "You are passing an array of ActiveRecord::Base instances to `update`. " \ "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`." end 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
#update!(id = :all, attributes)
# File 'activerecord/lib/active_record/persistence.rb', line 158
def update!(id = :all, attributes) if id.is_a?(Array) if id.any?(ActiveRecord::Base) raise ArgumentError, "You are passing an array of ActiveRecord::Base instances to `update!`. " \ "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`." end 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