2010-07-19 19:55:18 +08:00
|
|
|
= Active Record -- Object-relational mapping put on 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
|
|
|
|
class and an existing table in the database. In 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*.
|
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
|
|
|
|
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.
|
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
class Product < ActiveRecord::Base
|
|
|
|
end
|
2010-08-14 13:13:00 +08:00
|
|
|
|
2010-07-19 19:55:18 +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
|
|
|
|
2004-11-24 09:04:44 +08:00
|
|
|
CREATE TABLE products (
|
|
|
|
id int(11) NOT NULL auto_increment,
|
|
|
|
name varchar(255),
|
|
|
|
PRIMARY KEY (id)
|
|
|
|
);
|
2010-08-14 13:13:00 +08:00
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
This would also define the following accessors: `Product#name` and
|
|
|
|
`Product#name=(new_name)`
|
2010-08-14 13:13:00 +08:00
|
|
|
|
2005-02-24 01:25:41 +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
|
|
|
|
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
* Aggregations of value objects.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
class Account < ActiveRecord::Base
|
|
|
|
composed_of :balance, :class_name => "Money",
|
|
|
|
:mapping => %w(balance amount)
|
2010-08-14 13:13:00 +08:00
|
|
|
composed_of :address,
|
2004-11-24 09:04:44 +08:00
|
|
|
:mapping => [%w(address_street street), %w(address_city city)]
|
|
|
|
end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{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
|
|
|
|
validates_presence_of :subdomain, :name, :email_address, :password
|
|
|
|
validates_uniqueness_of :subdomain
|
|
|
|
validates_acceptance_of :terms_of_service, :on => :create
|
|
|
|
validates_confirmation_of :password, :email_address, :on => :create
|
|
|
|
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
|
|
|
|
|
|
|
|
2010-08-26 15:55:26 +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
|
|
|
|
|
|
|
|
2010-07-19 19:55:18 +08:00
|
|
|
* Observers that react to changes in a model
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
class CommentObserver < ActiveRecord::Observer
|
|
|
|
def after_create(comment) # is called just after Comment#save
|
2010-12-18 03:41:58 +08:00
|
|
|
CommentMailer.new_comment_email("david@loudthinking.com", comment)
|
2004-11-24 09:04:44 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Observer.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2010-08-14 13:13:00 +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
|
|
|
|
|
|
|
|
2008-04-05 11:52:58 +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
|
|
|
|
|
|
|
|
|
|
|
* 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
|
|
|
|
|
2005-02-24 01:25:41 +08:00
|
|
|
{Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
2010-07-19 19:55:18 +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
|
|
|
|
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(
|
2010-12-18 03:41:58 +08:00
|
|
|
:adapter => "mysql2",
|
2010-07-19 19:55:18 +08:00
|
|
|
:host => "localhost",
|
|
|
|
:username => "me",
|
|
|
|
:password => "secret",
|
|
|
|
:database => "activerecord"
|
|
|
|
)
|
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
|
|
|
|
MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html],
|
|
|
|
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
|
|
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
* Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
|
|
|
|
|
|
|
|
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
|
|
ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")
|
|
|
|
|
|
|
|
|
2008-05-04 00:29:47 +08:00
|
|
|
* Database agnostic schema management with Migrations
|
|
|
|
|
|
|
|
class AddSystemSettings < ActiveRecord::Migration
|
|
|
|
def self.up
|
|
|
|
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
|
|
|
|
|
|
|
|
SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.down
|
|
|
|
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)
|
|
|
|
pattern[http://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
|
|
|
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:
|
|
|
|
* No XML-files!
|
|
|
|
* 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
|
|
|
|
2010-07-21 17:56:28 +08:00
|
|
|
The latest version of Active Record can be installed with Rubygems:
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
% [sudo] gem install activerecord
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
Source code can be downloaded as part of the Rails project on GitHub
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2011-03-07 04:56:02 +08:00
|
|
|
* https://github.com/rails/rails/tree/master/activerecord/
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
== License
|
|
|
|
|
2005-02-24 10:07:02 +08:00
|
|
|
Active Record is released under the MIT license.
|
2004-11-24 09:04:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
== Support
|
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
API documentation is at
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
* http://api.rubyonrails.com
|
2004-11-24 09:04:44 +08:00
|
|
|
|
2010-07-18 20:58:40 +08:00
|
|
|
Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
|
|
|
|
|
2011-05-11 00:30:06 +08:00
|
|
|
* https://github.com/rails/rails/issues
|