Active Record – Ruby on Rails 中的对象关系映射¶ ↑
Active Record 将类连接到关系型数据库表,为应用程序建立几乎零配置的持久层。该库提供了一个基类,当被继承时,它会在新类和数据库中现有的表之间建立映射。在应用程序中,这些类通常被称为 **模型**。模型也可以与其他模型关联;这是通过定义 **关联** 来实现的。
Active Record 严重依赖命名,因为它使用类名和关联名来建立相应数据库表和外键列之间的映射。尽管可以显式定义这些映射,但建议遵循命名约定,尤其是在开始使用该库时。
您可以在 Active Record 基础知识 指南中阅读更多关于 Active Record 的信息。
一些主要功能的简要介绍
-
类和表、属性和列之间的自动映射。
class Product < ActiveRecord::Base end
Product 类会自动映射到名为“products”的表,该表可能如下所示:
CREATE TABLE products ( id bigint NOT NULL auto_increment, name varchar(255), PRIMARY KEY (id) );
这还会定义以下访问器:
Product#name和Product#name=(new_name)。 -
关联通过简单的类方法在对象之间建立。class Firm < ActiveRecord::Base has_many :clients has_one :account belongs_to :conglomerate end
-
聚合值对象。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
-
验证规则,对于新对象或现有对象可以不同。
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
-
在整个生命周期(实例化、保存、销毁、验证等)中都可以使用的
回调。class Person < ActiveRecord::Base before_destroy :invalidate_payment_plan # the `invalidate_payment_plan` method gets called just before Person#destroy end
-
继承层级。class Company < ActiveRecord::Base; end class Firm < Company; end class Client < Company; end class PriorityClient < Client; end
-
事务.# Database transaction Account.transaction do david.withdrawal(100) mary.deposit(100) end
-
关于列、关联和聚合的反射。
reflection = Firm.reflect_on_association(:clients) reflection.klass # => Client (class) Firm.columns # Returns an array of column descriptors for the firms table
-
通过简单的适配器实现数据库抽象。
# 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' )
了解更多 并阅读内置对 MySQL、PostgreSQL 和 SQLite3 的支持。
-
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
-
通过 Migrations 实现数据库无关的模式管理。
class AddSystemSettings < ActiveRecord::Migration[8.1] 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
理念¶ ↑
Active Record 是 Martin Fowler 所描述的同名 模式 的对象关系映射(ORM)实现。
“一个包装数据库表或视图中的一行,封装数据库访问,并在该数据上添加域逻辑的对象。”
Active Record 试图提供一个连贯的包装器,以解决对象关系映射带来的不便。该映射的首要指令是最大程度地减少构建真实域模型所需的代码量。通过依赖一系列约定,Active Record 可以轻松地从最少的显式指示中推断出复杂的关联和结构。
约定优于配置
-
无 XML 文件!
-
大量反射和运行时扩展
-
魔术(Magic)本身不是一个坏词
承认数据库
-
允许您在特殊情况和性能方面直接使用 SQL。
-
不试图复制或替换数据定义
下载和安装¶ ↑
最新版本的 Active Record 可以通过 RubyGems 安装。
$ gem install activerecord
源代码可以作为 Rails 项目的一部分在 GitHub 上下载。
许可证¶ ↑
Active Record 在 MIT 许可证下发布。
支持¶ ↑
API 文档位于:
Ruby on Rails 项目的错误报告可在此处提交:
功能请求应在此处的 rubyonrails-core 论坛上讨论:
用于包装关联记录错误的验证错误类,支持 index_errors。
- 模块 ActiveRecord::Aggregations
- 模块 ActiveRecord::Assertions
- 模块 ActiveRecord::Associations
- 模块 ActiveRecord::AttributeAssignment
- 模块 ActiveRecord::AttributeMethods
- 模块 ActiveRecord::Attributes
- 模块 ActiveRecord::AutosaveAssociation
- 模块 ActiveRecord::Batches
- 模块 ActiveRecord::Calculations
- 模块 ActiveRecord::Callbacks
- 模块 ActiveRecord::Coders
- 模块 ActiveRecord::ConnectionAdapters
- 模块 ActiveRecord::ConnectionHandling
- 模块 ActiveRecord::Core
- 模块 ActiveRecord::CounterCache
- 模块 ActiveRecord::DelegatedType
- 模块 ActiveRecord::DynamicMatchers
- 模块 ActiveRecord::Encryption
- 模块 ActiveRecord::Enum
- 模块 ActiveRecord::Explain
- 模块 ActiveRecord::FinderMethods
- 模块 ActiveRecord::Inheritance
- 模块 ActiveRecord::Integration
- 模块 ActiveRecord::Locking
- 模块 ActiveRecord::Marshalling
- 模块 ActiveRecord::MessagePack
- 模块 ActiveRecord::Middleware
- 模块 ActiveRecord::ModelSchema
- 模块 ActiveRecord::NestedAttributes
- 模块 ActiveRecord::NoTouching
- 模块 ActiveRecord::Persistence
- 模块 ActiveRecord::QueryLogs
- 模块 ActiveRecord::QueryMethods
- 模块 ActiveRecord::Querying
- 模块 ActiveRecord::ReadonlyAttributes
- 模块 ActiveRecord::Reflection
- 模块 ActiveRecord::RuntimeRegistry
- 模块 ActiveRecord::Sanitization
- 模块 ActiveRecord::Scoping
- 模块 ActiveRecord::SecurePassword
- 模块 ActiveRecord::SecureToken
- 模块 ActiveRecord::Serialization
- 模块 ActiveRecord::SignedId
- 模块 ActiveRecord::SpawnMethods
- 模块 ActiveRecord::Store
- 模块 ActiveRecord::Suppressor
- 模块 ActiveRecord::Tasks
- 模块 ActiveRecord::TestFixtures
- 模块 ActiveRecord::Timestamp
- 模块 ActiveRecord::TokenFor
- 模块 ActiveRecord::Transactions
- 模块 ActiveRecord::Translation
- 模块 ActiveRecord::Type
- 模块 ActiveRecord::VERSION
- 模块 ActiveRecord::Validations
- 类 ActiveRecord::ActiveRecordError
- 类 ActiveRecord::AdapterError
- 类 ActiveRecord::AdapterNotFound
- 类 ActiveRecord::AdapterNotSpecified
- 类 ActiveRecord::AdapterTimeout
- 类 ActiveRecord::AssociationTypeMismatch
- 类 ActiveRecord::AsynchronousQueryInsideTransactionError
- 类 ActiveRecord::AttributeAssignmentError
- 类 ActiveRecord::Base
- 类 ActiveRecord::CheckViolation
- 类 ActiveRecord::ConfigurationError
- 类 ActiveRecord::ConnectionFailed
- 类 ActiveRecord::ConnectionNotDefined
- 类 ActiveRecord::ConnectionNotEstablished
- 类 ActiveRecord::ConnectionTimeoutError
- 类 ActiveRecord::DangerousAttributeError
- 类 ActiveRecord::DatabaseAlreadyExists
- 类 ActiveRecord::DatabaseConfigurations
- 类 ActiveRecord::DatabaseConnectionError
- 类 ActiveRecord::DatabaseVersionError
- 类 ActiveRecord::Deadlocked
- 类 ActiveRecord::DeprecatedAssociationError
- 类 ActiveRecord::DestroyAssociationAsyncError
- 类 ActiveRecord::DestroyAssociationAsyncJob
- 类 ActiveRecord::EagerLoadPolymorphicError
- 类 ActiveRecord::EnvironmentMismatchError
- 类 ActiveRecord::ExclusionViolation
- 类 ActiveRecord::ExclusiveConnectionTimeoutError
- 类 ActiveRecord::ExplainRegistry
- 类 ActiveRecord::FixtureSet
- 类 ActiveRecord::FutureResult
- 类 ActiveRecord::InvalidForeignKey
- 类 ActiveRecord::IrreversibleMigration
- 类 ActiveRecord::IrreversibleOrderError
- 类 ActiveRecord::LockWaitTimeout
- 类 ActiveRecord::Migration
- 类 ActiveRecord::MigrationContext
- 类 ActiveRecord::MismatchedForeignKey
- 类 ActiveRecord::MissingRequiredOrderError
- 类 ActiveRecord::MultiparameterAssignmentErrors
- 类 ActiveRecord::NoDatabaseError
- 类 ActiveRecord::NotNullViolation
- 类 ActiveRecord::PreparedStatementCacheExpired
- 类 ActiveRecord::PreparedStatementInvalid
- 类 ActiveRecord::Promise
- 类 ActiveRecord::QueryAborted
- 类 ActiveRecord::QueryCache
- 类 ActiveRecord::QueryCanceled
- 类 ActiveRecord::RangeError
- 类 ActiveRecord::ReadOnlyError
- 类 ActiveRecord::ReadOnlyRecord
- 类 ActiveRecord::ReadonlyAttributeError
- 类 ActiveRecord::RecordInvalid
- 类 ActiveRecord::RecordNotDestroyed
- 类 ActiveRecord::RecordNotFound
- 类 ActiveRecord::RecordNotSaved
- 类 ActiveRecord::RecordNotUnique
- 类 ActiveRecord::Relation
- 类 ActiveRecord::Result
- 类 ActiveRecord::Rollback
- 类 ActiveRecord::SQLWarning
- 类 ActiveRecord::Schema
- 类 ActiveRecord::SerializationFailure
- 类 ActiveRecord::SerializationTypeMismatch
- 类 ActiveRecord::SoleRecordExceeded
- 类 ActiveRecord::StaleObjectError
- 类 ActiveRecord::StatementCache
- 类 ActiveRecord::StatementInvalid
- 类 ActiveRecord::StatementTimeout
- 类 ActiveRecord::StrictLoadingViolationError
- 类 ActiveRecord::SubclassNotFound
- 类 ActiveRecord::TableNotSpecified
- 类 ActiveRecord::Transaction
- 类 ActiveRecord::TransactionIsolationError
- 类 ActiveRecord::TransactionRollbackError
- 类 ActiveRecord::UnknownAttributeError
- 类 ActiveRecord::UnknownAttributeReference
- 类 ActiveRecord::UnknownPrimaryKey
- 类 ActiveRecord::UnmodifiableRelation
- 类 ActiveRecord::ValueTooLong
- 类 ActiveRecord::WrappedDatabaseException
- A
- D
- E
- G
- L
- M
- P
- Q
- R
- S
- T
- U
- V
- W
- Y
常量
| 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 |
|
||
| Point | = | Struct.new(:x, :y) |
| UnknownAttributeError | = | ActiveModel::UnknownAttributeError |
Active Model UnknownAttributeError¶ ↑在通过质量赋值提供未知属性时引发。 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 | |
| [RW] | database_cli | |
| [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] | raise_on_missing_required_finder_order_columns | |
| [RW] | reading_role | |
| [RW] | run_after_transaction_callbacks_in_order_defined | |
| [RW] | writing_role |
类公共方法
action_on_strict_loading_violation Link
设置应用程序在关联违反严格加载时记录或引发异常。默认为 `:raise`。
after_all_transactions_commit(&block) Link
注册一个块,在所有当前事务提交后调用。
如果没有当前打开的事务,块将立即调用。
如果有多个嵌套事务,块将在最外层事务提交后调用。
如果任何当前打开的事务被回滚,块将永远不会被调用。
如果有多个事务在多个数据库上打开,当所有事务都提交后,该块将被调用。但请注意,跨两个不同数据库的嵌套事务是分片反模式,会带来很多问题。
# File activerecord/lib/active_record.rb, line 573 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
async_query_executor Link
为应用程序设置 `async_query_executor`。默认情况下,线程池执行程序设置为 `nil`,这不会在后台运行查询。应用程序必须配置一个线程池执行程序才能使用此功能。选项有:
* 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.
db_warnings_action Link
当数据库查询产生警告时要采取的操作。必须是 `:ignore`、`:log`、`:raise`、`:report` 或自定义 proc 之一。默认为 `:ignore`。
db_warnings_action=(action) Link
# File activerecord/lib/active_record.rb, line 237 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 Link
指定数据库警告的允许列表。可以是字符串、正则表达式或数据库的错误代码。
ActiveRecord::Base.db_warnings_ignore = [/`SHOW WARNINGS` did not return the warnings/, "01000"]
default_timezone=(default_timezone) Link
确定是从数据库中读取日期和时间时使用 `Time.utc`(使用 `:utc`)还是 `Time.local`(使用 `:local`)。默认为 `:utc`。
deprecated_associations_options() Link
deprecated_associations_options=(options) Link
# File activerecord/lib/active_record.rb, line 479 def self.deprecated_associations_options=(options) raise ArgumentError, "deprecated_associations_options must be a hash" unless options.is_a?(Hash) valid_keys = [:mode, :backtrace] invalid_keys = options.keys - valid_keys unless invalid_keys.empty? inflected_key = invalid_keys.size == 1 ? "key" : "keys" raise ArgumentError, "invalid deprecated_associations_options #{inflected_key} #{invalid_keys.map(&:inspect).to_sentence} (valid keys are #{valid_keys.map(&:inspect).to_sentence})" end options.each do |key, value| ActiveRecord::Associations::Deprecation.send("#{key}=", value) end end
disconnect_all!() Link
显式关闭所有连接池中的所有数据库连接。
dump_schema_after_migration Link
指定 `bin/rails db:migrate` 命令结束时是否应进行模式转储。默认情况下此值为 `true`,这在开发环境中很有用。在生产环境中,此值最好为 `false`,因为在生产环境中很少需要转储模式。
dump_schemas Link
指定调用 `db:schema:dump` 时要转储的数据库模式。如果值为 `:schema_search_path`(默认值),则转储 `schema_search_path` 中列出的任何模式。使用 `:all` 来转储所有模式(无论 `schema_search_path` 如何),或使用逗号分隔的字符串来指定自定义列表。
eager_load!() Link
# File activerecord/lib/active_record.rb, line 545 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 Link
指定在批处理查询中忽略 `order` 时是否应引发错误。当应用程序中的作用域被视为错误而不是警告时很有用。
gem_version() Link
将当前加载的 Active Record 版本作为 `Gem::Version` 返回。
generate_secure_token_on Link
控制何时为 `has_secure_token` 声明生成值。默认为 `:create`。
global_executor_concurrency=(global_executor_concurrency) Link
设置 `global_executor_concurrency`。此配置值只能与全局线程池异步查询执行程序一起使用。
# File activerecord/lib/active_record.rb, line 304 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 Link
延迟加载模式缓存。此选项将在建立连接时加载模式缓存,而不是在启动时加载。
marshalling_format_version() Link
marshalling_format_version=(value) Link
message_verifiers Link
`ActiveSupport::MessageVerifiers` 实例用于 Active Record。如果您正在使用 `Rails`,它将被设置为 `Rails.application.message_verifiers`。
migration_strategy Link
指定用于执行迁移的策略。
permanent_connection_checkout=(value) Link
定义 `ActiveRecord::Base.connection` 是允许、已弃用还是完全禁止。
# File activerecord/lib/active_record.rb, line 320 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 Link
在数据库协议/DBMS 和要使用的底层数据库适配器之间提供映射。这仅由 `DATABASE_URL` 环境变量使用。
示例¶ ↑
DATABASE_URL="mysql://myuser:mypass@localhost/somedatabase"
上述 URL 指定 MySQL 是所需的协议/DBMS,然后应用程序配置可以选择使用哪个适配器。在此示例中,默认映射是从 `mysql` 到 `mysql2`,但也支持 `:trilogy`。
ActiveRecord.protocol_adapters.mysql = "mysql2"
协议名称是任意的,并且可以在此处注册和设置外部数据库适配器。
queues Link
指定后台作业使用的队列名称。
raise_int_wider_than_64bit Link
应用程序可配置的布尔值,表示 PostgreSQLAdapter 是否在提供大于 64 位有符号整数的值时引发异常。
schema_cache_ignored_table?(table_name) Link
通过检查 `schema_cache_ignored_tables` 选项来判断 `table_name` 是否被忽略。
ActiveRecord.schema_cache_ignored_table?(:developers)
schema_cache_ignored_tables Link
在转储模式缓存时要忽略的表或匹配表的正则表达式列表。例如,如果此选项设置为 `[/^_/]`,则模式缓存将不会转储以下划线开头的表。
schema_format Link
指定使用 Rails 的 Rakefile 转储数据库模式时使用的格式。如果为 `:sql`,则模式将作为(可能是特定于数据库的)SQL 语句转储。如果为 `:ruby`,则模式将作为可以加载到任何支持迁移的数据库中的 `ActiveRecord::Schema` 文件转储。如果您希望为您的开发和测试环境使用不同的数据库适配器,请使用 `:ruby`。这可以在数据库配置中为每个数据库单独覆盖。
schema_versions_formatter Link
指定模式转储程序用于格式化版本信息的分隔符。
timestamped_migrations Link
指定是否使用时间戳作为迁移版本。
use_yaml_unsafe_load Link
应用程序可配置的布尔值,指示 YAML 编码器在设置为 `true` 时使用不安全的加载。
validate_migration_timestamps Link
指定是否验证迁移时间戳。设置为 `true` 时,如果时间戳比当前时间相关时间戳早一天以上,将引发错误。必须将 `timestamped_migrations` 设置为 `true`。
verbose_query_logs Link
指定是否应在数据库查询旁边记录调用数据库查询的方法。默认为 `false`。
verify_foreign_keys_for_fixtures Link
如果为 `true`,`Rails` 将在加载 fixture 后验证数据库中的所有外键。如果存在任何外键冲突,将引发错误,表明 fixture 编写不正确。支持 PostgreSQL 和 SQLite。
version() Link
将当前加载的 Active Record 版本作为 `Gem::Version` 返回。
with_transaction_isolation_level(isolation_level, &block) Link
在块中的所有连接池中设置事务隔离级别。
# File activerecord/lib/active_record.rb, line 616 def self.with_transaction_isolation_level(isolation_level, &block) original_level = self.default_transaction_isolation_level self.default_transaction_isolation_level = isolation_level yield ensure self.default_transaction_isolation_level = original_level end