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