Skip to Content Skip to Search

Active Record – Object-relational mapping in Rails

Active Record connects classes to relational database tables to establish an almost zero-configuration persistence layer for applications. The library provides a base class that, when subclassed, sets up a mapping between the new class and an existing table in the database. In the context of an application, these classes are commonly referred to as models. Models can also be connected to other models; this is done by defining associations.

Active Record relies heavily on naming in that it uses class and association names to establish mappings between respective database tables and foreign key columns. Although these mappings can be defined explicitly, it’s recommended to follow naming conventions, especially when getting started with the library.

You can read more about Active Record in the Active Record Basics guide.

A short rundown of some of the major features:

  • Automated mapping between classes and tables, attributes and columns.

    class Product < ActiveRecord::Base
    end
    

    The Product class is automatically mapped to the table named “products”, which might look like this:

    CREATE TABLE products (
      id bigint NOT NULL auto_increment,
      name varchar(255),
      PRIMARY KEY  (id)
    );
    

    This would also define the following accessors: Product#name and Product#name=(new_name).

    Learn more

  • Associations between objects defined by simple class methods.

    class Firm < ActiveRecord::Base
      has_many   :clients
      has_one    :account
      belongs_to :conglomerate
    end
    

    Learn more

  • Aggregations of value objects.

    class Account < ActiveRecord::Base
      composed_of :balance, class_name: 'Money',
                  mapping: %w(balance amount)
      composed_of :address,
                  mapping: [%w(address_street street), %w(address_city city)]
    end
    

    Learn more

  • Validation rules that can differ for new or existing objects.

    class Account < ActiveRecord::Base
      validates :subdomain, :name, :email_address, :password, presence: true
      validates :subdomain, uniqueness: true
      validates :terms_of_service, acceptance: true, on: :create
      validates :password, :email_address, confirmation: true, on: :create
    end
    

    Learn more

  • Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).

    class Person < ActiveRecord::Base
      before_destroy :invalidate_payment_plan
      # the `invalidate_payment_plan` method gets called just before Person#destroy
    end
    

    Learn more

  • Inheritance hierarchies.

    class Company < ActiveRecord::Base; end
    class Firm < Company; end
    class Client < Company; end
    class PriorityClient < Client; end
    

    Learn more

  • Transactions.

    # Database transaction
    Account.transaction do
      david.withdrawal(100)
      mary.deposit(100)
    end
    

    Learn more

  • Reflections on columns, associations, and aggregations.

    reflection = Firm.reflect_on_association(:clients)
    reflection.klass # => Client (class)
    Firm.columns # Returns an array of column descriptors for the firms table
    

    Learn more

  • Database abstraction through simple adapters.

    # connect to SQLite3
    ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3')
    
    # connect to MySQL with authentication
    ActiveRecord::Base.establish_connection(
      adapter:  'mysql2',
      host:     'localhost',
      username: 'me',
      password: 'secret',
      database: 'activerecord'
    )
    

    Learn more and read about the built-in support for MySQL, PostgreSQL, and SQLite3.

  • Logging support for Log4r and Logger.

    ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
    ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
    
  • Database agnostic schema management with Migrations.

    class AddSystemSettings < ActiveRecord::Migration[7.2]
      def up
        create_table :system_settings do |t|
          t.string  :name
          t.string  :label
          t.text    :value
          t.string  :type
          t.integer :position
        end
    
        SystemSetting.create name: 'notice', label: 'Use notice?', value: 1
      end
    
      def down
        drop_table :system_settings
      end
    end
    

    Learn more

Philosophy

Active Record is an implementation of the object-relational mapping (ORM) pattern by the same name described by Martin Fowler:

“An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.”

Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is object-relational mapping. The prime directive for this mapping has been to minimize the amount of code needed to build a real-world domain model. This is made possible by relying on a number of conventions that make it easy for Active Record to infer complex relations and structures from a minimal amount of explicit direction.

Convention over Configuration:

  • No XML files!

  • Lots of reflection and run-time extension

  • Magic is not inherently a bad word

Admit the Database:

  • Lets you drop down to SQL for odd cases and performance

  • Doesn’t attempt to duplicate or replace data definitions

Download and installation

The latest version of Active Record can be installed with RubyGems:

$ gem install activerecord

Source code can be downloaded as part of the Rails project on GitHub:

License

Active Record is released under the MIT license:

Support

API documentation is at:

Bug reports for the Ruby on Rails project can be filed here:

Feature requests should be discussed on the rails-core mailing list here:

Validation error class to wrap association records’ errors, with index_errors support.

Namespace
Methods
A
C
D
E
G
L
M
P
Q
R
S
T
U
V
W
Y
Included Modules

Constants

MigrationProxy = Struct.new(:name, :version, :filename, :scope) do def initialize(name, version, filename, scope) super @migration = nil end def basename File.basename(filename) end delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration private def migration @migration ||= load_migration end def load_migration Object.send(:remove_const, name) rescue nil load(File.expand_path(filename)) name.constantize.new(name, version) end end
 

MigrationProxy is used to defer loading of the actual migration classes until they are needed

Point = Struct.new(:x, :y)
 
UnknownAttributeError = ActiveModel::UnknownAttributeError
 

Active Model UnknownAttributeError

Raised when unknown attributes are supplied via mass assignment.

class Person
  include ActiveModel::AttributeAssignment
  include ActiveModel::Validations
end

person = Person.new
person.assign_attributes(name: 'Gorby')
# => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person.

Attributes

[RW] application_record_class
[RW] before_committed_on_all_records
[RW] belongs_to_required_validates_foreign_key
[R] default_timezone
[RW] disable_prepared_statements
[RW] index_nested_attribute_errors
[RW] maintain_test_schema
[R] permanent_connection_checkout
[RW] query_transformers
[RW] raise_on_assign_to_attr_readonly
[RW] reading_role
[RW] run_after_transaction_callbacks_in_order_defined
[RW] writing_role

Class Public methods

action_on_strict_loading_violation

Set the application to log or raise when an association violates strict loading. Defaults to :raise.

# File activerecord/lib/active_record.rb, line 377
singleton_class.attr_accessor :action_on_strict_loading_violation

after_all_transactions_commit(&block)

Registers a block to be called after all the current transactions have been committed.

If there is no currently open transaction, the block is called immediately.

If there are multiple nested transactions, the block is called after the outermost one has been committed,

If any of the currently open transactions is rolled back, the block is never called.

If multiple transactions are open across multiple databases, the block will be invoked if and once all of them have been committed. But note that nesting transactions across two distinct databases is a sharding anti-pattern that comes with a world of hurts.

# File activerecord/lib/active_record.rb, line 557
def self.after_all_transactions_commit(&block)
  open_transactions = all_open_transactions

  if open_transactions.empty?
    yield
  elsif open_transactions.size == 1
    open_transactions.first.after_commit(&block)
  else
    count = open_transactions.size
    callback = -> do
      count -= 1
      block.call if count.zero?
    end
    open_transactions.each do |t|
      t.after_commit(&callback)
    end
    open_transactions = nil # rubocop:disable Lint/UselessAssignment avoid holding it in the closure
  end
end

allow_deprecated_singular_associations_name()

# File activerecord/lib/active_record.rb, line 447
  def self.allow_deprecated_singular_associations_name
    ActiveRecord.deprecator.warn <<-WARNING.squish
      `Rails.application.config.active_record.allow_deprecated_singular_associations_name`
      is deprecated and will be removed in Rails 8.0.
    WARNING
  end

allow_deprecated_singular_associations_name=(value)

# File activerecord/lib/active_record.rb, line 454
  def self.allow_deprecated_singular_associations_name=(value)
    ActiveRecord.deprecator.warn <<-WARNING.squish
      `Rails.application.config.active_record.allow_deprecated_singular_associations_name`
      is deprecated and will be removed in Rails 8.0.
    WARNING
  end

async_query_executor

Sets the async_query_executor for an application. By default the thread pool executor set to nil which will not run queries in the background. Applications must configure a thread pool executor to use this feature. Options are:

* nil - Does not initialize a thread pool executor. Any async calls will be
run in the foreground.
* :global_thread_pool - Initializes a single +Concurrent::ThreadPoolExecutor+
that uses the +async_query_concurrency+ for the +max_threads+ value.
* :multi_thread_pool - Initializes a +Concurrent::ThreadPoolExecutor+ for each
database connection. The initializer values are defined in the configuration hash.
# File activerecord/lib/active_record.rb, line 276
singleton_class.attr_accessor :async_query_executor

commit_transaction_on_non_local_return()

# File activerecord/lib/active_record.rb, line 347
  def self.commit_transaction_on_non_local_return
    ActiveRecord.deprecator.warn <<-WARNING.squish
      `Rails.application.config.active_record.commit_transaction_on_non_local_return`
      is deprecated and will be removed in Rails 8.0.
    WARNING
  end

commit_transaction_on_non_local_return=(value)

# File activerecord/lib/active_record.rb, line 354
  def self.commit_transaction_on_non_local_return=(value)
    ActiveRecord.deprecator.warn <<-WARNING.squish
      `Rails.application.config.active_record.commit_transaction_on_non_local_return`
      is deprecated and will be removed in Rails 8.0.
    WARNING
  end

db_warnings_action

The action to take when database query produces warning. Must be one of :ignore, :log, :raise, :report, or a custom proc. The default is :ignore.

# File activerecord/lib/active_record.rb, line 218
singleton_class.attr_reader :db_warnings_action

db_warnings_action=(action)

# File activerecord/lib/active_record.rb, line 220
def self.db_warnings_action=(action)
  @db_warnings_action =
    case action
    when :ignore
      nil
    when :log
      ->(warning) do
        warning_message = "[#{warning.class}] #{warning.message}"
        warning_message += " (#{warning.code})" if warning.code
        ActiveRecord::Base.logger.warn(warning_message)
      end
    when :raise
      ->(warning) { raise warning }
    when :report
      ->(warning) { Rails.error.report(warning, handled: true) }
    when Proc
      action
    else
      raise ArgumentError, "db_warnings_action must be one of :ignore, :log, :raise, :report, or a custom proc."
    end
end

db_warnings_ignore

Specify allowlist of database warnings.

# File activerecord/lib/active_record.rb, line 247
singleton_class.attr_accessor :db_warnings_ignore

default_timezone=(default_timezone)

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.

# File activerecord/lib/active_record.rb, line 203
def self.default_timezone=(default_timezone)
  unless %i(local utc).include?(default_timezone)
    raise ArgumentError, "default_timezone must be either :utc (default) or :local."
  end

  @default_timezone = default_timezone
end

disconnect_all!()

Explicitly closes all database connections in all pools.

# File activerecord/lib/active_record.rb, line 540
def self.disconnect_all!
  ConnectionAdapters::PoolConfig.disconnect_all!
end

dump_schema_after_migration

Specify whether schema dump should happen at the end of the bin/rails db:migrate 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.

# File activerecord/lib/active_record.rb, line 425
singleton_class.attr_accessor :dump_schema_after_migration

dump_schemas

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.

# File activerecord/lib/active_record.rb, line 435
singleton_class.attr_accessor :dump_schemas

eager_load!()

# File activerecord/lib/active_record.rb, line 529
def self.eager_load!
  super
  ActiveRecord::Locking.eager_load!
  ActiveRecord::Scoping.eager_load!
  ActiveRecord::Associations.eager_load!
  ActiveRecord::AttributeMethods.eager_load!
  ActiveRecord::ConnectionAdapters.eager_load!
  ActiveRecord::Encryption.eager_load!
end

error_on_ignored_order

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.

# File activerecord/lib/active_record.rb, line 396
singleton_class.attr_accessor :error_on_ignored_order

gem_version()

Returns the currently loaded version of Active Record as a Gem::Version.

# File activerecord/lib/active_record/gem_version.rb, line 5
def self.gem_version
  Gem::Version.new VERSION::STRING
end

generate_secure_token_on

Controls when to generate a value for has_secure_token declarations. Defaults to :create.

# File activerecord/lib/active_record.rb, line 490
singleton_class.attr_accessor :generate_secure_token_on

global_executor_concurrency=(global_executor_concurrency)

Set the global_executor_concurrency. This configuration value can only be used with the global thread pool async query executor.

# File activerecord/lib/active_record.rb, line 291
def self.global_executor_concurrency=(global_executor_concurrency)
  if self.async_query_executor.nil? || self.async_query_executor == :multi_thread_pool
    raise ArgumentError, "`global_executor_concurrency` cannot be set when the executor is nil or set to `:multi_thread_pool`. For multiple thread pools, please set the concurrency in your database configuration."
  end

  @global_executor_concurrency = global_executor_concurrency
end

lazily_load_schema_cache

Lazily load the schema cache. This option will load the schema cache when a connection is established rather than on boot.

# File activerecord/lib/active_record.rb, line 188
singleton_class.attr_accessor :lazily_load_schema_cache

legacy_connection_handling=(_)

# File activerecord/lib/active_record.rb, line 256
  def self.legacy_connection_handling=(_)
    raise ArgumentError, <<~MSG.squish
      The `legacy_connection_handling` setter was deprecated in 7.0 and removed in 7.1,
      but is still defined in your configuration. Please remove this call as it no longer
      has any effect."
    MSG
  end

marshalling_format_version()

# File activerecord/lib/active_record.rb, line 493
def self.marshalling_format_version
  Marshalling.format_version
end

marshalling_format_version=(value)

# File activerecord/lib/active_record.rb, line 497
def self.marshalling_format_version=(value)
  Marshalling.format_version = value
end

migration_strategy

Specify strategy to use for executing migrations.

# File activerecord/lib/active_record.rb, line 416
singleton_class.attr_accessor :migration_strategy

permanent_connection_checkout=(value)

Defines whether ActiveRecord::Base.connection is allowed, deprecated, or entirely disallowed.

# File activerecord/lib/active_record.rb, line 307
def self.permanent_connection_checkout=(value)
  unless [true, :deprecated, :disallowed].include?(value)
    raise ArgumentError, "permanent_connection_checkout must be one of: `true`, `:deprecated` or `:disallowed`"
  end
  @permanent_connection_checkout = value
end

protocol_adapters

Provides a mapping between database protocols/DBMSs and the underlying database adapter to be used. This is used only by the DATABASE_URL environment variable.

Example

DATABASE_URL="mysql://myuser:mypass@localhost/somedatabase"

The above URL specifies that MySQL is the desired protocol/DBMS, and the application configuration can then decide which adapter to use. For this example the default mapping is from mysql to mysql2, but :trilogy is also supported.

ActiveRecord.protocol_adapters.mysql = "mysql2"

The protocols names are arbitrary, and external database adapters can be registered and set here.

# File activerecord/lib/active_record.rb, line 520
singleton_class.attr_accessor :protocol_adapters

queues

Specifies the names of the queues used by background jobs.

# File activerecord/lib/active_record.rb, line 329
singleton_class.attr_accessor :queues

raise_int_wider_than_64bit

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

# File activerecord/lib/active_record.rb, line 476
singleton_class.attr_accessor :raise_int_wider_than_64bit

schema_cache_ignored_tables

A list of tables or regex’s to match tables to ignore when dumping the schema cache. For example if this is set to +[/^_/]+ the schema cache will not dump tables named with an underscore.

# File activerecord/lib/active_record.rb, line 196
singleton_class.attr_accessor :schema_cache_ignored_tables

schema_format

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.

# File activerecord/lib/active_record.rb, line 388
singleton_class.attr_accessor :schema_format

timestamped_migrations

Specify whether or not to use timestamps for migration versions

# File activerecord/lib/active_record.rb, line 402
singleton_class.attr_accessor :timestamped_migrations

use_yaml_unsafe_load

Application configurable boolean that instructs the YAML Coder to use an unsafe load if set to true.

# File activerecord/lib/active_record.rb, line 468
singleton_class.attr_accessor :use_yaml_unsafe_load

validate_migration_timestamps

Specify whether or not to validate migration timestamps. When set, an error will be raised if a timestamp is more than a day ahead of the timestamp associated with the current time. timestamped_migrations must be set to true.

# File activerecord/lib/active_record.rb, line 410
singleton_class.attr_accessor :validate_migration_timestamps

verbose_query_logs

Specifies if the methods calling database queries should be logged below their relevant queries. Defaults to false.

# File activerecord/lib/active_record.rb, line 322
singleton_class.attr_accessor :verbose_query_logs

verify_foreign_keys_for_fixtures

If true, Rails will verify all foreign keys in the database after loading fixtures. An error will be raised if there are any foreign key violations, indicating incorrectly written fixtures. Supported by PostgreSQL and SQLite.

# File activerecord/lib/active_record.rb, line 444
singleton_class.attr_accessor :verify_foreign_keys_for_fixtures

version()

Returns the currently loaded version of Active Record as a Gem::Version.

# File activerecord/lib/active_record/version.rb, line 7
def self.version
  gem_version
end

warn_on_records_fetched_greater_than

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.

# File activerecord/lib/active_record.rb, line 367
singleton_class.attr_accessor :warn_on_records_fetched_greater_than

yaml_column_permitted_classes

Application configurable array that provides additional permitted classes to Psych safe_load in the YAML Coder

# File activerecord/lib/active_record.rb, line 483
singleton_class.attr_accessor :yaml_column_permitted_classes