Module: ActiveRecord::Core
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::ActiveSupport::Concern
|
|
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
-
#frozen? ⇒ Boolean
readonly
Returns
true
if the attributes hash has been frozen. -
#readonly? ⇒ Boolean
readonly
Returns
true
if the record is read only. -
#strict_loading? ⇒ Boolean
readonly
Returns
true
if the record is in strict_loading mode. -
#strict_loading_all? ⇒ Boolean
readonly
Returns
true
if the record uses strict_loading with:all
mode enabled. - #strict_loading_mode readonly
-
#strict_loading_n_plus_one_only? ⇒ Boolean
readonly
Returns
true
if the record uses strict_loading with:n_plus_one_only
mode enabled.
Instance Method Summary
-
#<=>(other_object)
Allows sort on objects.
-
#==(comparison_object)
(also: #eql?)
Returns true if
comparison_object
is the same exact object, orcomparison_object
is of the same type andself
has an ID and it is equal tocomparison_object.id
. - #all_attributes_for_inspect
- #attributes_for_inspect
-
#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.
-
#full_inspect
Returns all attributes of the record as a nicely formatted string, ignoring #attributes_for_inspect.
-
#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 attributes of the record as a nicely formatted string.
- #inspect_with_attributes(attributes_to_list)
- #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!(value = true, mode: :all)
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 ]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
# File 'activerecord/lib/active_record/core.rb', line 14
included do ## # :singleton-method: # # Accepts a logger conforming to the interface of Log4r or the default # Ruby Logger class, which is then passed on to any new database # connections made. You can retrieve this logger by calling logger on # either an Active Record model class or an Active Record model instance. class_attribute :logger, instance_writer: false class_attribute :_destroy_association_async_job, instance_accessor: false, default: "ActiveRecord::DestroyAssociationAsyncJob" # The job class used to destroy associations in the background. def self.destroy_association_async_job if _destroy_association_async_job.is_a?(String) self._destroy_association_async_job = _destroy_association_async_job.constantize end _destroy_association_async_job rescue NameError => error raise NameError, "Unable to load destroy_association_async_job: #{error.}" end singleton_class.alias_method :destroy_association_async_job=, :_destroy_association_async_job= delegate :destroy_association_async_job, to: :class ## # :singleton-method: # # Specifies the maximum number of records that will be destroyed in a # single background job by the <tt>dependent: :destroy_async</tt> # association option. When nil (default), all dependent records will be # destroyed in a single background job. If specified, the records to be # destroyed will be split into multiple background jobs. class_attribute :destroy_association_async_batch_size, instance_writer: false, instance_predicate: false, default: nil ## # 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: storage/development.sqlite3 # # production: # adapter: sqlite3 # database: storage/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: "storage/development.sqlite3"}>, # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production", # @name="primary", @config={adapter: "sqlite3", database: "storage/production.sqlite3"}> # ]> def self.configurations=(config) @@configurations = ActiveRecord::DatabaseConfigurations.new(config) end self.configurations = {} # Returns a fully resolved ActiveRecord::DatabaseConfigurations object. def self.configurations @@configurations end ## # :singleton-method: # Force enumeration of all columns in SELECT statements. # e.g. <tt>SELECT first_name, last_name FROM ...</tt> instead of <tt>SELECT * FROM ...</tt> # This avoids PreparedStatementCacheExpired errors when a column is added # to the database while the app is running. class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false class_attribute :belongs_to_required_by_default, instance_accessor: false class_attribute :strict_loading_by_default, instance_accessor: false, default: false class_attribute :strict_loading_mode, instance_accessor: false, default: :all class_attribute :has_many_inversing, instance_accessor: false, default: false class_attribute :run_commit_callbacks_on_first_saved_instances_in_transaction, instance_accessor: false, default: true class_attribute :default_connection_handler, instance_writer: false class_attribute :default_role, instance_writer: false class_attribute :default_shard, instance_writer: false class_attribute :shard_selector, instance_accessor: false, default: nil ## # :singleton-method: # # Specifies the attributes that will be included in the output of the # #inspect method: # # Post.attributes_for_inspect = [:id, :title] # Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">" # # When set to :all inspect will list all the record's attributes: # # Post.attributes_for_inspect = :all # Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">" class_attribute :attributes_for_inspect, instance_accessor: false, default: :all def self.application_record_class? # :nodoc: if ActiveRecord.application_record_class self == ActiveRecord.application_record_class else if defined?(ApplicationRecord) && self == ApplicationRecord true end end end self.filter_attributes = [] def self.connection_handler ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler end def self.connection_handler=(handler) ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler end def self.asynchronous_queries_session # :nodoc: asynchronous_queries_tracker.current_session end def self.asynchronous_queries_tracker # :nodoc: ActiveSupport::IsolatedExecutionState[:active_record_asynchronous_queries_tracker] ||= \ AsynchronousQueriesTracker.new 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 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_class_for_self) end default_role 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_class_for_self) 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 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_class_for_self) end false end def self.connected_to_stack # :nodoc: if connected_to_stack = ActiveSupport::IsolatedExecutionState[:active_record_connected_to_stack] connected_to_stack else connected_to_stack = Concurrent::Array.new ActiveSupport::IsolatedExecutionState[:active_record_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_class_for_self # :nodoc: klass = self until klass == Base break if klass.connection_class? klass = klass.superclass end klass end self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new self.default_role = ActiveRecord.writing_role self.default_shard = :default def self.strict_loading_violation!(owner:, reflection:) # :nodoc: case ActiveRecord.action_on_strict_loading_violation when :raise = reflection. (owner) raise ActiveRecord::StrictLoadingViolationError.new( ) 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.
# File 'activerecord/lib/active_record/core.rb', line 649
def frozen? @attributes.frozen? end
#readonly? ⇒ Boolean
(readonly)
Returns true
if the record is read only.
# File 'activerecord/lib/active_record/core.rb', line 671
def readonly? @readonly end
#strict_loading? ⇒ Boolean
(readonly)
Returns true
if the record is in strict_loading mode.
# File 'activerecord/lib/active_record/core.rb', line 676
def strict_loading? @strict_loading end
#strict_loading_all? ⇒ Boolean
(readonly)
Returns true
if the record uses strict_loading with :all
mode enabled.
# File 'activerecord/lib/active_record/core.rb', line 726
def strict_loading_all? @strict_loading_mode == :all end
#strict_loading_mode (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 718
attr_reader :strict_loading_mode
#strict_loading_n_plus_one_only? ⇒ Boolean
(readonly)
Returns true
if the record uses strict_loading with :n_plus_one_only
mode enabled.
# File 'activerecord/lib/active_record/core.rb', line 721
def strict_loading_n_plus_one_only? @strict_loading_mode == :n_plus_one_only end
Instance Method Details
#<=>(other_object)
Allows sort on objects
# File 'activerecord/lib/active_record/core.rb', line 654
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.
# File 'activerecord/lib/active_record/core.rb', line 620
def ==(comparison_object) super || comparison_object.instance_of?(self.class) && primary_key_values_present? && comparison_object.id == id end
#all_attributes_for_inspect
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 859
def all_attributes_for_inspect return [] unless @attributes attribute_names end
#attributes_for_inspect
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 855
def attributes_for_inspect self.class.attributes_for_inspect == :all ? all_attributes_for_inspect : self.class.attributes_for_inspect 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
# File 'activerecord/lib/active_record/core.rb', line 512
rdoc_method :method: clone
#connection_handler
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 739
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) and locking column.
# File 'activerecord/lib/active_record/core.rb', line 529
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, ... }}
# File 'activerecord/lib/active_record/core.rb', line 576
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 #==.
# File 'activerecord/lib/active_record/core.rb', line 626
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.
# File 'activerecord/lib/active_record/core.rb', line 643
def freeze @attributes = @attributes.clone.freeze self end
#full_inspect
Returns all attributes of the record as a nicely formatted string, ignoring #attributes_for_inspect.
Post.first.full_inspect
#=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
# File 'activerecord/lib/active_record/core.rb', line 763
def full_inspect inspect_with_attributes(all_attributes_for_inspect) 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) ]
# File 'activerecord/lib/active_record/core.rb', line 630
def hash id = self.id if self.class.composite_primary_key? ? primary_key_values_present? : 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'
# File 'activerecord/lib/active_record/core.rb', line 487
def init_with(coder, &block) coder = LegacyYamlAdapter.convert(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')
# File 'activerecord/lib/active_record/core.rb', line 460
def initialize(attributes = nil) @new_record = true @attributes = self.class._default_attributes.deep_dup init_internals initialize_internals_callback super yield self if block_given? _run_initialize_callbacks end
#inspect
Returns the attributes of the record as a nicely formatted string.
Post.first.inspect
#=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
The attributes can be limited by setting #attributes_for_inspect.
Post.attributes_for_inspect = [:id, :title]
Post.first.inspect
#=> "#<Post id: 1, title: "Hello, World!">"
# File 'activerecord/lib/active_record/core.rb', line 753
def inspect inspect_with_attributes(attributes_for_inspect) end
#inspect_with_attributes(attributes_to_list)
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 840
def inspect_with_attributes(attributes_to_list) inspection = if @attributes attributes_to_list.filter_map do |name| name = name.to_s if _has_attribute?(name) "#{name}: #{attribute_for_inspect(name)}" end end.join(", ") else "not initialized" end "#<#{self.class} #{inspection}>" end
#inspection_filter
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 836
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.
# File 'activerecord/lib/active_record/core.rb', line 769
def pretty_print(pp) return super if custom_inspect_method_defined? pp.object_address_group(self) do if @attributes attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) } pp.seplist(attr_names, proc { pp.text "," }) do |attr_name| attr_name = attr_name.to_s pp.breakable " " pp.group(1) do pp.text attr_name pp.text ":" pp.breakable value = attribute_for_inspect(attr_name) pp.text value end end else pp.breakable " " pp.text "not initialized" end end end
#readonly!
Marks this record as read only.
customer = Customer.first
customer.readonly!
customer.save # Raises an ActiveRecord::ReadOnlyRecord
# File 'activerecord/lib/active_record/core.rb', line 735
def readonly! @readonly = true end
#slice(*methods)
Returns a hash of the given methods with their names as keys and returned values as values.
topic = Topic.new(title: "Budget", author_name: "Jason")
topic.slice(:title, : )
#=> { "title" => "Budget", "author_name" => "Jason" }
# File 'activerecord/lib/active_record/core.rb', line 583
rdoc_method :method: slice
#strict_loading!(value = true, mode: :all)
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! # => true
user.address.city
#=> ActiveRecord::StrictLoadingViolationError
user.comments.to_a
#=> ActiveRecord::StrictLoadingViolationError
Parameters
-
value
- Boolean specifying whether to enable or disable strict loading. -
:mode
-::Symbol
specifying strict loading mode. Defaults to:all
. Using :n_plus_one_only mode will only raise an error if an association that will lead to an n plus one query is lazily loaded.
Examples
user = User.first
user.strict_loading!(false) # => false
user.address.city # => "Tatooine"
user.comments.to_a # => [#<Comment:0x00...]
user.strict_loading!(mode: :n_plus_one_only)
user.address.city # => "Tatooine"
user.comments.to_a # => [#<Comment:0x00...]
user.comments.first. .to_a
#=> ActiveRecord::StrictLoadingViolationError
# File 'activerecord/lib/active_record/core.rb', line 709
def strict_loading!(value = true, mode: :all) unless [:all, :n_plus_one_only].include?(mode) raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only] but #{mode.inspect} was provided." end @strict_loading_mode = mode @strict_loading = value end
#values_at(*methods)
Returns an array of the values returned by the given methods.
topic = Topic.new(title: "Budget", author_name: "Jason")
topic.values_at(:title, : )
#=> ["Budget", "Jason"]
# File 'activerecord/lib/active_record/core.rb', line 598
rdoc_method :method: values_at