2023-06-23 09:49:30 +08:00
|
|
|
= Active Record -- Object-relational mapping in \Rails
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
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
|
2011-06-04 03:26:53 +08:00
|
|
|
class and an existing table in the database. In the context of an application,
|
2010-07-19 19:55:18 +08:00
|
|
|
these classes are commonly referred to as *models*. Models can also be
|
|
|
|
connected to other models; this is done by defining *associations*.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
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.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2023-02-04 08:01:00 +08:00
|
|
|
You can read more about Active Record in the {Active Record Basics}[https://guides.rubyonrails.org/active_record_basics.html] guide.
|
2019-03-10 05:47:01 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
A short rundown of some of the major features:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
* Automated mapping between classes and tables, attributes and columns.
|
|
|
|
|
2022-12-27 04:55:17 +08:00
|
|
|
class Product < ActiveRecord::Base
|
|
|
|
end
|
2014-05-12 23:37:37 +08:00
|
|
|
|
2022-12-27 04:55:17 +08:00
|
|
|
The Product class is automatically mapped to the table named "products",
|
|
|
|
which might look like this:
|
2010-08-14 13:13:00 +08:00
|
|
|
|
2022-12-27 04:55:17 +08:00
|
|
|
CREATE TABLE products (
|
|
|
|
id bigint NOT NULL auto_increment,
|
|
|
|
name varchar(255),
|
|
|
|
PRIMARY KEY (id)
|
|
|
|
);
|
2010-08-14 13:13:00 +08:00
|
|
|
|
2022-12-27 04:55:17 +08:00
|
|
|
This would also define the following accessors: <tt>Product#name</tt> and
|
|
|
|
<tt>Product#name=(new_name)</tt>.
|
2014-05-12 23:37:37 +08:00
|
|
|
|
2022-12-27 04:55:17 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Base.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
* Associations between objects defined by simple class methods.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
class Firm < ActiveRecord::Base
|
|
|
|
has_many :clients
|
|
|
|
has_one :account
|
2010-07-19 19:55:18 +08:00
|
|
|
belongs_to :conglomerate
|
2004-11-24 09:04:44 +08:00
|
|
|
end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Associations/ClassMethods.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2012-07-28 05:21:29 +08:00
|
|
|
* Aggregations of value objects.
|
|
|
|
|
|
|
|
class Account < ActiveRecord::Base
|
2012-09-17 13:28:05 +08:00
|
|
|
composed_of :balance, class_name: 'Money',
|
|
|
|
mapping: %w(balance amount)
|
2012-07-28 05:21:29 +08:00
|
|
|
composed_of :address,
|
2012-09-17 13:28:05 +08:00
|
|
|
mapping: [%w(address_street street), %w(address_city city)]
|
2012-07-28 05:21:29 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
|
|
|
|
|
|
|
|
|
2004-11-24 09:04:44 +08:00
|
|
|
* Validation rules that can differ for new or existing objects.
|
|
|
|
|
2004-12-17 00:23:59 +08:00
|
|
|
class Account < ActiveRecord::Base
|
2012-05-28 14:45:33 +08:00
|
|
|
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
|
2004-12-17 00:23:59 +08:00
|
|
|
end
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Validations.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).
|
2010-07-19 19:55:18 +08:00
|
|
|
|
|
|
|
class Person < ActiveRecord::Base
|
|
|
|
before_destroy :invalidate_payment_plan
|
|
|
|
# the `invalidate_payment_plan` method gets called just before Person#destroy
|
2004-11-24 09:04:44 +08:00
|
|
|
end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Callbacks.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Inheritance hierarchies.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
class Company < ActiveRecord::Base; end
|
|
|
|
class Firm < Company; end
|
|
|
|
class Client < Company; end
|
|
|
|
class PriorityClient < Client; end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Base.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Transactions.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2008-04-05 11:52:58 +08:00
|
|
|
# Database transaction
|
2004-11-24 09:04:44 +08:00
|
|
|
Account.transaction do
|
|
|
|
david.withdrawal(100)
|
|
|
|
mary.deposit(100)
|
|
|
|
end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Reflections on columns, associations, and aggregations.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
reflection = Firm.reflect_on_association(:clients)
|
|
|
|
reflection.klass # => Client (class)
|
|
|
|
Firm.columns # Returns an array of column descriptors for the firms table
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Database abstraction through simple adapters.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
# connect to SQLite3
|
2012-09-17 13:28:05 +08:00
|
|
|
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3')
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
# connect to MySQL with authentication
|
|
|
|
ActiveRecord::Base.establish_connection(
|
2012-09-17 13:28:05 +08:00
|
|
|
adapter: 'mysql2',
|
|
|
|
host: 'localhost',
|
|
|
|
username: 'me',
|
|
|
|
password: 'secret',
|
|
|
|
database: 'activerecord'
|
2010-07-19 19:55:18 +08:00
|
|
|
)
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
|
2015-12-21 07:46:55 +08:00
|
|
|
MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
|
2010-07-19 19:55:18 +08:00
|
|
|
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
|
|
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2019-09-09 08:34:09 +08:00
|
|
|
* Logging support for Log4r[https://github.com/colbygk/log4r] and Logger[https://ruby-doc.org/stdlib/libdoc/logger/rdoc/].
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2012-01-05 02:52:24 +08:00
|
|
|
ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
|
2012-09-17 13:28:05 +08:00
|
|
|
ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2011-06-04 03:26:53 +08:00
|
|
|
* Database agnostic schema management with Migrations.
|
2008-05-04 00:29:47 +08:00
|
|
|
|
2023-09-27 11:59:11 +08:00
|
|
|
class AddSystemSettings < ActiveRecord::Migration[7.2]
|
2011-11-07 10:56:50 +08:00
|
|
|
def up
|
2008-05-04 00:29:47 +08:00
|
|
|
create_table :system_settings do |t|
|
2010-07-19 19:55:18 +08:00
|
|
|
t.string :name
|
|
|
|
t.string :label
|
|
|
|
t.text :value
|
|
|
|
t.string :type
|
|
|
|
t.integer :position
|
2008-05-04 00:29:47 +08:00
|
|
|
end
|
|
|
|
|
2012-09-17 13:28:05 +08:00
|
|
|
SystemSetting.create name: 'notice', label: 'Use notice?', value: 1
|
2008-05-04 00:29:47 +08:00
|
|
|
end
|
|
|
|
|
2011-11-07 10:56:50 +08:00
|
|
|
def down
|
2008-05-04 00:29:47 +08:00
|
|
|
drop_table :system_settings
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
{Learn more}[link:classes/ActiveRecord/Migration.html]
|
|
|
|
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-08-14 13:13:00 +08:00
|
|
|
== Philosophy
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
Active Record is an implementation of the object-relational mapping (ORM)
|
2017-08-22 07:46:02 +08:00
|
|
|
pattern[https://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
2010-07-19 19:55:18 +08:00
|
|
|
name described by Martin Fowler:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
"An object that wraps a row in a database table or view,
|
|
|
|
encapsulates the database access, and adds domain logic on that data."
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-08-14 13:13:00 +08:00
|
|
|
Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is
|
2004-11-24 09:04:44 +08:00
|
|
|
object-relational mapping. The prime directive for this mapping has been to minimize
|
2005-11-07 17:51:47 +08:00
|
|
|
the amount of code needed to build a real-world domain model. This is made possible
|
2004-11-24 09:04:44 +08:00
|
|
|
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:
|
2013-05-07 08:22:18 +08:00
|
|
|
* No XML files!
|
2004-11-24 09:04:44 +08:00
|
|
|
* Lots of reflection and run-time extension
|
2010-08-14 13:13:00 +08:00
|
|
|
* Magic is not inherently a bad word
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
Admit the Database:
|
|
|
|
* Lets you drop down to SQL for odd cases and performance
|
|
|
|
* Doesn't attempt to duplicate or replace data definitions
|
|
|
|
|
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
== Download and installation
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2011-08-05 16:34:43 +08:00
|
|
|
The latest version of Active Record can be installed with RubyGems:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2015-12-07 02:16:26 +08:00
|
|
|
$ gem install activerecord
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2023-05-29 14:14:44 +08:00
|
|
|
Source code can be downloaded as part of the \Rails project on GitHub:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2021-01-20 04:43:24 +08:00
|
|
|
* https://github.com/rails/rails/tree/main/activerecord
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
== License
|
|
|
|
|
2011-12-24 05:03:21 +08:00
|
|
|
Active Record is released under the MIT license:
|
|
|
|
|
2017-08-22 07:46:02 +08:00
|
|
|
* https://opensource.org/licenses/MIT
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
== Support
|
|
|
|
|
2013-03-15 09:03:17 +08:00
|
|
|
API documentation is at:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2019-03-09 20:08:03 +08:00
|
|
|
* https://api.rubyonrails.org
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2023-05-29 14:14:44 +08:00
|
|
|
Bug reports for the Ruby on \Rails project can be filed here:
|
2010-07-18 20:58:40 +08:00
|
|
|
|
2011-05-11 00:30:06 +08:00
|
|
|
* https://github.com/rails/rails/issues
|
2014-06-02 10:11:39 +08:00
|
|
|
|
|
|
|
Feature requests should be discussed on the rails-core mailing list here:
|
|
|
|
|
2020-03-26 14:21:37 +08:00
|
|
|
* https://discuss.rubyonrails.org/c/rubyonrails-core
|