Module: ActiveRecord::Persistence::ClassMethods
- Defined in:
- lib/active_record/persistence.rb
Instance Method Summary collapse
-
#_delete_record(constraints) ⇒ Object
:nodoc:.
-
#_insert_record(connection, values, returning) ⇒ Object
:nodoc:.
-
#_update_record(values, constraints) ⇒ Object
:nodoc:.
-
#build(attributes = nil, &block) ⇒ Object
Builds an object (or multiple objects) and returns either the built object or a list of built objects.
-
#composite_query_constraints_list ⇒ Object
Returns an array of column names to be used in queries.
-
#create(attributes = nil, &block) ⇒ Object
Creates an object (or multiple objects) and saves it to the database, if validations pass.
-
#create!(attributes = nil, &block) ⇒ Object
Creates an object (or multiple objects) and saves it to the database, if validations pass.
-
#has_query_constraints? ⇒ Boolean
:nodoc:.
-
#instantiate(attributes, column_types = {}, &block) ⇒ Object
Given an attributes hash,
instantiate
returns a new instance of the appropriate class. -
#query_constraints(*columns_list) ⇒ Object
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. -
#query_constraints_list ⇒ Object
:nodoc:.
-
#update(id = :all, attributes) ⇒ Object
Updates an object (or multiple objects) and saves it to the database, if validations pass.
-
#update!(id = :all, attributes) ⇒ Object
Updates the object (or multiple objects) just like #update but calls #update! instead of
update
, so an exception is raised if the record is invalid and saving will fail.
Instance Method Details
#_delete_record(constraints) ⇒ Object
:nodoc:
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File '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) ⇒ Object
:nodoc:
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File '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) ⇒ Object
:nodoc:
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File '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) ⇒ Object
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
82 83 84 85 86 87 88 |
# File '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 |
#composite_query_constraints_list ⇒ Object
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.
234 235 236 |
# File '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) ⇒ Object
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
33 34 35 36 37 38 39 40 41 |
# File 'lib/active_record/persistence.rb', line 33 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 |
#create!(attributes = nil, &block) ⇒ Object
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.
50 51 52 53 54 55 56 57 58 |
# File 'lib/active_record/persistence.rb', line 50 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 |
#has_query_constraints? ⇒ Boolean
:nodoc:
219 220 221 |
# File 'lib/active_record/persistence.rb', line 219 def has_query_constraints? # :nodoc: @has_query_constraints end |
#instantiate(attributes, column_types = {}, &block) ⇒ Object
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.
100 101 102 103 |
# File '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 |
#query_constraints(*columns_list) ⇒ Object
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
212 213 214 215 216 217 |
# File '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 ⇒ Object
:nodoc:
223 224 225 226 227 228 229 |
# File '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) ⇒ Object
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.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File '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) ⇒ Object
Updates the object (or multiple objects) just like #update but calls #update! instead of update
, so an exception is raised if the record is invalid and saving will fail.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File '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 |