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 trueif the attributes hash has been frozen.
- 
    
      #readonly?  ⇒ Boolean 
    
    readonly
    Returns trueif the record is read only.
- 
    
      #strict_loading?  ⇒ Boolean 
    
    readonly
    Returns trueif the record is in strict_loading mode.
- 
    
      #strict_loading_all?  ⇒ Boolean 
    
    readonly
    Returns trueif the record uses strict_loading with:allmode enabled.
- #strict_loading_mode readonly
- 
    
      #strict_loading_n_plus_one_only?  ⇒ Boolean 
    
    readonly
    Returns trueif the record uses strict_loading with:n_plus_one_onlymode enabled.
Instance Method Summary
- 
    
      #<=>(other_object)  
    
    Allows sort on objects. 
- 
    
      #==(comparison_object)  
      (also: #eql?)
    
    Returns true if comparison_objectis the same exact object, orcomparison_objectis of the same type andselfhas 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 coderwith 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 recordwhen pp is required.
- 
    
      #readonly!  
    
    Prevents records from being written to the database: 
- 
    
      #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
# 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 :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 645
def frozen? @attributes.frozen? end
    #readonly?  ⇒ Boolean  (readonly)
  
Returns true if the record is read only.
# File 'activerecord/lib/active_record/core.rb', line 667
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 672
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 724
def strict_loading_all? @strict_loading_mode == :all end
#strict_loading_mode (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 716
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 719
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 650
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 616
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 875
def all_attributes_for_inspect return [] unless @attributes attribute_names end
#attributes_for_inspect
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 871
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 515
rdoc_method :method: clone
#connection_handler
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 755
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 532
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 572
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 622
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 639
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 779
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 626
def hash id = self.id if primary_key_values_present? 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 490
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 463
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 769
def inspect inspect_with_attributes(attributes_for_inspect) end
#inspect_with_attributes(attributes_to_list)
[ GitHub ]# File 'activerecord/lib/active_record/core.rb', line 856
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 852
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 785
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!
Prevents records from being written to the database:
customer = Customer.new
customer.readonly!
customer.save # raises ActiveRecord::ReadOnlyRecord
customer = Customer.first
customer.readonly!
customer.update(name: 'New Name') # raises ActiveRecord::ReadOnlyRecordRead-only records cannot be deleted from the database either:
customer = Customer.first
customer.readonly!
customer.destroy # raises ActiveRecord::ReadOnlyRecordPlease, note that the objects themselves are still mutable in memory:
customer = Customer.new
customer.readonly!
customer.name = 'New Name' # OKbut you won’t be able to persist the changes.
# File 'activerecord/lib/active_record/core.rb', line 751
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 579
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.
NOTE: Strict loading is disabled during validation in order to let the record validate its association.
user = User.first
user.strict_loading! # => true
user.address.city
# => ActiveRecord::StrictLoadingViolationError
user.comments.to_a
# => ActiveRecord::StrictLoadingViolationErrorParameters
- 
value- Boolean specifying whether to enable or disable strict loading.
- 
:mode-::Symbolspecifying 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 707
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 594
rdoc_method :method: values_at