123456789_123456789_123456789_123456789_123456789_

Module: ActiveRecord::Core

Relationships & Source Files
Namespace Children
Modules:
Extension / Inclusion / Inheritance Descendants
Included In:
Base, ActiveRecord::InternalMetadata, ActiveRecord::SchemaMigration
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Defined in: activerecord/lib/active_record/core.rb

Class Method Summary

::ActiveSupport::Concern - Extended

class_methods

Define class methods from given block.

included

Evaluate given block in context of base class, so that you can write class macros here.

prepended

Evaluate given block in context of base class, so that you can write class macros here.

Instance Attribute Summary

Instance Method Summary

  • #<=>(other_object)

    Allows sort on objects.

  • #==(comparison_object) (also: #eql?)

    Returns true if comparison_object is the same exact object, or comparison_object is of the same type and self has an ID and it is equal to comparison_object.id.

  • #clone

    Identical to Ruby’s clone method.

  • #connection_handler
  • #dup

    Duped objects have no id assigned and are treated as new records.

  • #encode_with(coder)

    Populate coder with attributes about this record that should be serialized.

  • #eql?(comparison_object)

    Alias for #==.

  • #freeze

    Clone and freeze the attributes hash such that associations are still accessible, even on destroyed records, but cloned models will not be frozen.

  • #hash

    Delegates to id in order to allow two records of the same type and id to work with something like:

  • #init_with(coder, &block)

    Initialize an empty model object from coder.

  • #initialize(attributes = nil) {|_self| ... }

    New objects can be instantiated as either empty (pass no construction parameter) or pre-set with attributes but not yet saved (pass a hash with key names matching the associated table column names).

  • #inspect

    Returns the contents of the record as a nicely formatted string.

  • #inspection_filter
  • #pretty_print(pp)

    Takes a PP and prettily prints this record to it, allowing you to get a nice result from pp record when pp is required.

  • #readonly!

    Marks this record as read only.

  • #slice(*methods)

    Returns a hash of the given methods with their names as keys and returned values as values.

  • #strict_loading!

    Sets the record to strict_loading mode.

  • #values_at(*methods)

    Returns an array of the values returned by the given methods.

DSL Calls

included

[ GitHub ]


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'activerecord/lib/active_record/core.rb', line 13

included do
  ##
  # :singleton-method:
  #
  # Accepts a logger conforming to the interface of Log4r which is then
  # passed on to any new database connections made and which can be
  # retrieved on both a class and instance level by calling logger.
  mattr_accessor :logger, instance_writer: false

  ##
  # :singleton-method:
  #
  # Specifies if the methods calling database queries should be logged below
  # their relevant queries. Defaults to false.
  mattr_accessor :verbose_query_logs, instance_writer: false, default: false

  ##
  # :singleton-method:
  #
  # Specifies the names of the queues used by background jobs.
  mattr_accessor :queues, instance_accessor: false, default: {}

  ##
  # :singleton-method:
  #
  # Specifies the job used to destroy associations in the background
  class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false

  ##
  # Contains the database configuration - as is typically stored in config/database.yml -
  # as an ActiveRecord::DatabaseConfigurations object.
  #
  # For example, the following database.yml...
  #
  #   development:
  #     adapter: sqlite3
  #     database: db/development.sqlite3
  #
  #   production:
  #     adapter: sqlite3
  #     database: db/production.sqlite3
  #
  # ...would result in ActiveRecord::Base.configurations to look like this:
  #
  #   #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
  #     #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
  #       @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
  #     #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
  #       @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
  #   ]>
  def self.configurations=(config)
    @@configurations = ActiveRecord::DatabaseConfigurations.new(config)
  end
  self.configurations = {}

  # Returns fully resolved ActiveRecord::DatabaseConfigurations object
  def self.configurations
    @@configurations
  end

  ##
  # :singleton-method:
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
  # dates and times from the database. This is set to :utc by default.
  mattr_accessor :default_timezone, instance_writer: false, default: :utc

  ##
  # :singleton-method:
  # Specifies the format to use when dumping the database schema with Rails'
  # Rakefile. If :sql, the schema is dumped as (potentially database-
  # specific) SQL statements. If :ruby, the schema is dumped as an
  # ActiveRecord::Schema file which can be loaded into any database that
  # supports migrations. Use :ruby if you want to have different database
  # adapters for, e.g., your development and test environments.
  mattr_accessor :schema_format, instance_writer: false, default: :ruby

  ##
  # :singleton-method:
  # Specifies if an error should be raised if the query has an order being
  # ignored when doing batch queries. Useful in applications where the
  # scope being ignored is error-worthy, rather than a warning.
  mattr_accessor :error_on_ignored_order, instance_writer: false, default: false

  ##
  # :singleton-method:
  # Specify whether or not to use timestamps for migration versions
  mattr_accessor :timestamped_migrations, instance_writer: false, default: true

  ##
  # :singleton-method:
  # Specify whether schema dump should happen at the end of the
  # db:migrate rails command. This is true by default, which is useful for the
  # development environment. This should ideally be false in the production
  # environment where dumping schema is rarely needed.
  mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true

  ##
  # :singleton-method:
  # Specifies which database schemas to dump when calling db:schema:dump.
  # If the value is :schema_search_path (the default), any schemas listed in
  # schema_search_path are dumped. Use :all to dump all schemas regardless
  # of schema_search_path, or a string of comma separated schemas for a
  # custom list.
  mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path

  ##
  # :singleton-method:
  # Specify a threshold for the size of query result sets. If the number of
  # records in the set exceeds the threshold, a warning is logged. This can
  # be used to identify queries which load thousands of records and
  # potentially cause memory bloat.
  mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false

  ##
  # :singleton-method:
  # Show a warning when Rails couldn't parse your database.yml
  # for multiple databases.
  mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false

  mattr_accessor :maintain_test_schema, instance_accessor: false

  class_attribute :belongs_to_required_by_default, instance_accessor: false

  ##
  # :singleton-method:
  # Set the application to log or raise when an association violates strict loading.
  # Defaults to :raise.
  mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise

  class_attribute :strict_loading_by_default, instance_accessor: false, default: false

  mattr_accessor :writing_role, instance_accessor: false, default: :writing

  mattr_accessor :reading_role, instance_accessor: false, default: :reading

  mattr_accessor :has_many_inversing, instance_accessor: false, default: false

  class_attribute :default_connection_handler, instance_writer: false

  class_attribute :default_role, instance_writer: false

  class_attribute :default_shard, instance_writer: false

  mattr_accessor :legacy_connection_handling, instance_writer: false, default: true

  # Application configurable boolean that instructs the YAML Coder to use
  # an unsafe load if set to true.
  mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false

  # Application configurable array that provides additional permitted classes
  # to Psych safe_load in the YAML Coder
  mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]

  ##
  # :singleton-method:
  # Application configurable boolean that denotes whether or not to raise
  # an exception when the PostgreSQLAdapter is provided with an integer that is
  # wider than signed 64bit representation
  mattr_accessor :raise_int_wider_than_64bit, instance_writer: false, default: true

  self.filter_attributes = []

  def self.connection_handler
    Thread.current.thread_variable_get(:ar_connection_handler) || default_connection_handler
  end

  def self.connection_handler=(handler)
    Thread.current.thread_variable_set(:ar_connection_handler, handler)
  end

  def self.connection_handlers
    unless legacy_connection_handling
      raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
    end

    @@connection_handlers ||= {}
  end

  def self.connection_handlers=(handlers)
    unless legacy_connection_handling
      raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
    end

    @@connection_handlers = handlers
  end

  # Returns the symbol representing the current connected role.
  #
  #   ActiveRecord::Base.connected_to(role: :writing) do
  #     ActiveRecord::Base.current_role #=> :writing
  #   end
  #
  #   ActiveRecord::Base.connected_to(role: :reading) do
  #     ActiveRecord::Base.current_role #=> :reading
  #   end
  def self.current_role
    if ActiveRecord::Base.legacy_connection_handling
      connection_handlers.key(connection_handler) || default_role
    else
      connected_to_stack.reverse_each do |hash|
        return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
        return hash[:role] if hash[:role] && hash[:klasses].include?(connection_classes)
      end

      default_role
    end
  end

  # Returns the symbol representing the current connected shard.
  #
  #   ActiveRecord::Base.connected_to(role: :reading) do
  #     ActiveRecord::Base.current_shard #=> :default
  #   end
  #
  #   ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
  #     ActiveRecord::Base.current_shard #=> :one
  #   end
  def self.current_shard
    connected_to_stack.reverse_each do |hash|
      return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
      return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_classes)
    end

    default_shard
  end

  # Returns the symbol representing the current setting for
  # preventing writes.
  #
  #   ActiveRecord::Base.connected_to(role: :reading) do
  #     ActiveRecord::Base.current_preventing_writes #=> true
  #   end
  #
  #   ActiveRecord::Base.connected_to(role: :writing) do
  #     ActiveRecord::Base.current_preventing_writes #=> false
  #   end
  def self.current_preventing_writes
    if legacy_connection_handling
      connection_handler.prevent_writes
    else
      connected_to_stack.reverse_each do |hash|
        return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
        return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_classes)
      end

      false
    end
  end

  def self.connected_to_stack # :nodoc:
    if connected_to_stack = Thread.current.thread_variable_get(:ar_connected_to_stack)
      connected_to_stack
    else
      connected_to_stack = Concurrent::Array.new
      Thread.current.thread_variable_set(:ar_connected_to_stack, connected_to_stack)
      connected_to_stack
    end
  end

  def self.connection_class=(b) # :nodoc:
    @connection_class = b
  end

  def self.connection_class # :nodoc
    @connection_class ||= false
  end

  def self.connection_class? # :nodoc:
    self.connection_class
  end

  def self.connection_classes # :nodoc:
    klass = self

    until klass == Base
      break if klass.connection_class?
      klass = klass.superclass
    end

    klass
  end

  def self.allow_unsafe_raw_sql # :nodoc:
    ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
  end

  def self.allow_unsafe_raw_sql=(value) # :nodoc:
    ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
  end

  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
  self.default_role = writing_role
  self.default_shard = :default

  def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
    case action_on_strict_loading_violation
    when :raise
      message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
      raise ActiveRecord::StrictLoadingViolationError.new(message)
    when :log
      name = "strict_loading_violation.active_record"
      ActiveSupport::Notifications.instrument(name, owner: owner, reflection: reflection)
    end
  end
end

Instance Attribute Details

#frozen?Boolean (readonly)

Returns true if the attributes hash has been frozen.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 664

def frozen?
  @attributes.frozen?
end

#readonly?Boolean (readonly)

Returns true if the record is read only.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 686

def readonly?
  @readonly
end

#strict_loading?Boolean (readonly)

Returns true if the record is in strict_loading mode.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 691

def strict_loading?
  @strict_loading
end

Instance Method Details

#<=>(other_object)

Allows sort on objects

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 669

def <=>(other_object)
  if other_object.is_a?(self.class)
    to_key <=> other_object.to_key
  else
    super
  end
end

#==(comparison_object) Also known as: #eql?

Returns true if comparison_object is the same exact object, or comparison_object is of the same type and self has an ID and it is equal to comparison_object.id.

Note that new records are different from any other record by definition, unless the other record is the receiver itself. Besides, if you fetch existing records with select and leave the ID out, you’re on your own, this predicate will return false.

Note also that destroying a record preserves its ID in the model instance, so deleted models are still comparable.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 637

def ==(comparison_object)
  super ||
    comparison_object.instance_of?(self.class) &&
    !id.nil? &&
    comparison_object.id == id
end

#clone

Identical to Ruby’s clone method. This is a “shallow” copy. Be warned that your attributes are not copied. That means that modifying attributes of the clone will modify the original, since they will both point to the same attributes hash. If you need a copy of your attributes hash, please use the #dup method.

user = User.first
new_user = user.clone
user.name               # => "Bob"
new_user.name = "Joe"
user.name               # => "Joe"

user.object_id == new_user.object_id            # => false
user.name.object_id == new_user.name.object_id  # => true

user.name.object_id == user.dup.name.object_id  # => false
[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 570

rdoc_method :method: clone

#connection_handler

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 711

def connection_handler
  self.class.connection_handler
end

#dup

Duped objects have no id assigned and are treated as new records. Note that this is a “shallow” copy as it copies the object’s attributes only, not its associations. The extent of a “deep” copy is application specific and is therefore left to the application to implement according to its need. The dup method does not preserve the timestamps (created|updated)_(at|on).

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 587

rdoc_method :method: dup

#encode_with(coder)

Populate coder with attributes about this record that should be serialized. The structure of coder defined in this method is guaranteed to match the structure of coder passed to the #init_with method.

Example:

class Post < ActiveRecord::Base
end
coder = {}
Post.new.encode_with(coder)
coder # => {"attributes" => {"id" => nil, ... }}
[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 622

def encode_with(coder)
  self.class.yaml_encoder.encode(@attributes, coder)
  coder["new_record"] = new_record?
  coder["active_record_yaml_version"] = 2
end

#eql?(comparison_object)

Alias for #==.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 643

alias :eql? :==

#freeze

Clone and freeze the attributes hash such that associations are still accessible, even on destroyed records, but cloned models will not be frozen.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 658

def freeze
  @attributes = @attributes.clone.freeze
  self
end

#hash

Delegates to id in order to allow two records of the same type and id to work with something like:

[ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 647

def hash
  if id
    self.class.hash ^ id.hash
  else
    super
  end
end

#init_with(coder, &block)

Initialize an empty model object from coder. coder should be the result of previously encoding an Active Record model, using #encode_with.

class Post < ActiveRecord::Base
end

old_post = Post.new(title: "hello world")
coder = {}
old_post.encode_with(coder)

post = Post.allocate
post.init_with(coder)
post.title # => 'hello world'
[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 545

def init_with(coder, &block)
  coder = LegacyYamlAdapter.convert(self.class, coder)
  attributes = self.class.yaml_encoder.decode(coder)
  init_with_attributes(attributes, coder["new_record"], &block)
end

#initialize(attributes = nil) {|_self| ... }

New objects can be instantiated as either empty (pass no construction parameter) or pre-set with attributes but not yet saved (pass a hash with key names matching the associated table column names). In both instances, valid attribute keys are determined by the column names of the associated table – hence you can’t have attributes that aren’t part of the table columns.

Example:

# Instantiates a single new object
User.new(first_name: 'Jamie')

Yields:

  • (_self)

Yield Parameters:

  • _self (Core)

    the object that the method was called on

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 518

def initialize(attributes = nil)
  @new_record = true
  @attributes = self.class._default_attributes.deep_dup

  init_internals
  initialize_internals_callback

  assign_attributes(attributes) if attributes

  yield self if block_given?
  _run_initialize_callbacks
end

#inspect

Returns the contents of the record as a nicely formatted string.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 716

def inspect
  # We check defined?(@attributes) not to issue warnings if the object is
  # allocated but not initialized.
  inspection = if defined?(@attributes) && @attributes
    self.class.attribute_names.collect do |name|
      if _has_attribute?(name)
        "#{name}: #{attribute_for_inspect(name)}"
      end
    end.compact.join(", ")
  else
    "not initialized"
  end

  "#<#{self.class} #{inspection}>"
end

#inspection_filter

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 807

def inspection_filter
  self.class.inspection_filter
end

#pretty_print(pp)

Takes a PP and prettily prints this record to it, allowing you to get a nice result from pp record when pp is required.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 734

def pretty_print(pp)
  return super if custom_inspect_method_defined?
  pp.object_address_group(self) do
    if defined?(@attributes) && @attributes
      attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
      pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
        pp.breakable " "
        pp.group(1) do
          pp.text attr_name
          pp.text ":"
          pp.breakable
          value = _read_attribute(attr_name)
          value = inspection_filter.filter_param(attr_name, value) unless value.nil?
          pp.pp value
        end
      end
    else
      pp.breakable " "
      pp.text "not initialized"
    end
  end
end

#readonly!

Marks this record as read only.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 707

def readonly!
  @readonly = true
end

#slice(*methods)

Returns a hash of the given methods with their names as keys and returned values as values.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 758

def slice(*methods)
  methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
end

#strict_loading!

Sets the record to strict_loading mode. This will raise an error if the record tries to lazily load an association.

user = User.first
user.strict_loading!
user.comments.to_a
#=> ActiveRecord::StrictLoadingViolationError
[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 702

def strict_loading!
  @strict_loading = true
end

#values_at(*methods)

Returns an array of the values returned by the given methods.

[ GitHub ]

  
# File 'activerecord/lib/active_record/core.rb', line 763

def values_at(*methods)
  methods.flatten.map! { |method| public_send(method) }
end