mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
219 lines
6.7 KiB
Text
219 lines
6.7 KiB
Text
= 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}[https://edgeguides.rubyonrails.org/active_record_basics.html] guide.
|
|
|
|
A short rundown of some of the major features:
|
|
|
|
* Automated mapping between classes and tables, attributes and columns.
|
|
|
|
class Product < ActiveRecord::Base
|
|
end
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Base.html]
|
|
|
|
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: <tt>Product#name</tt> and
|
|
<tt>Product#name=(new_name)</tt>.
|
|
|
|
|
|
* Associations between objects defined by simple class methods.
|
|
|
|
class Firm < ActiveRecord::Base
|
|
has_many :clients
|
|
has_one :account
|
|
belongs_to :conglomerate
|
|
end
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Associations/ClassMethods.html]
|
|
|
|
|
|
* 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}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
|
|
|
|
|
|
* 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}[link:classes/ActiveRecord/Validations.html]
|
|
|
|
|
|
* 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}[link:classes/ActiveRecord/Callbacks.html]
|
|
|
|
|
|
* Inheritance hierarchies.
|
|
|
|
class Company < ActiveRecord::Base; end
|
|
class Firm < Company; end
|
|
class Client < Company; end
|
|
class PriorityClient < Client; end
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Base.html]
|
|
|
|
|
|
* Transactions.
|
|
|
|
# Database transaction
|
|
Account.transaction do
|
|
david.withdrawal(100)
|
|
mary.deposit(100)
|
|
end
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
|
|
|
|
|
|
* 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}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
|
|
|
|
|
|
* 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}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
|
|
MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
|
|
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
|
|
|
|
|
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[https://ruby-doc.org/stdlib/libdoc/logger/rdoc/].
|
|
|
|
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[6.0]
|
|
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}[link:classes/ActiveRecord/Migration.html]
|
|
|
|
|
|
== Philosophy
|
|
|
|
Active Record is an implementation of the object-relational mapping (ORM)
|
|
pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] 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:
|
|
|
|
* https://github.com/rails/rails/tree/master/activerecord
|
|
|
|
|
|
== License
|
|
|
|
Active Record is released under the MIT license:
|
|
|
|
* https://opensource.org/licenses/MIT
|
|
|
|
|
|
== Support
|
|
|
|
API documentation is at:
|
|
|
|
* https://api.rubyonrails.org
|
|
|
|
Bug reports for the Ruby on Rails project can be filed here:
|
|
|
|
* https://github.com/rails/rails/issues
|
|
|
|
Feature requests should be discussed on the rails-core mailing list here:
|
|
|
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|