Skip to content
Newer
Older
100644 335 lines (220 sloc) 10.3 KB
db045db @dhh Initial
dhh authored
1 = Active Record -- Object-relation mapping put on rails
2
3 Active Record connects business objects and database tables to create a persistable
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
4 domain model where logic and data are presented in one wrapping. It's an implementation
db045db @dhh Initial
dhh authored
5 of the object-relational mapping (ORM) pattern[http://www.martinfowler.com/eaaCatalog/activeRecord.html]
6 by the same name as described by Martin Fowler:
7
8 "An object that wraps a row in a database table or view, encapsulates
9 the database access, and adds domain logic on that data."
10
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
11 Active Record's main contribution to the pattern is to relieve the original of two stunting problems:
db045db @dhh Initial
dhh authored
12 lack of associations and inheritance. By adding a simple domain language-like set of macros to describe
13 the former and integrating the Single Table Inheritance pattern for the latter, Active Record narrows the
14 gap of functionality between the data mapper and active record approach.
15
16 A short rundown of the major features:
17
18 * Automated mapping between classes and tables, attributes and columns.
19
20 class Product < ActiveRecord::Base; end
21
22 ...is automatically mapped to the table named "products", such as:
23
24 CREATE TABLE products (
25 id int(11) NOT NULL auto_increment,
26 name varchar(255),
27 PRIMARY KEY (id)
28 );
29
30 ...which again gives Product#name and Product#name=(new_name)
31
c4e5196 @dhh Updated documentation even more
dhh authored
32 {Learn more}[link:classes/ActiveRecord/Base.html]
db045db @dhh Initial
dhh authored
33
34
35 * Associations between objects controlled by simple meta-programming macros.
36
37 class Firm < ActiveRecord::Base
38 has_many :clients
39 has_one :account
40 belongs_to :conglomorate
41 end
42
c4e5196 @dhh Updated documentation even more
dhh authored
43 {Learn more}[link:classes/ActiveRecord/Associations/ClassMethods.html]
db045db @dhh Initial
dhh authored
44
45
46 * Aggregations of value objects controlled by simple meta-programming macros.
47
48 class Account < ActiveRecord::Base
49 composed_of :balance, :class_name => "Money",
50 :mapping => %w(balance amount)
51 composed_of :address,
52 :mapping => [%w(address_street street), %w(address_city city)]
53 end
54
c4e5196 @dhh Updated documentation even more
dhh authored
55 {Learn more}[link:classes/ActiveRecord/Aggregations/ClassMethods.html]
db045db @dhh Initial
dhh authored
56
57
58 * Validation rules that can differ for new or existing objects.
59
6860db6 @dhh Renamed Mixins to Acts to resemble the change from include ActiveReco…
dhh authored
60 class Account < ActiveRecord::Base
61 validates_presence_of :subdomain, :name, :email_address, :password
62 validates_uniqueness_of :subdomain
63 validates_acceptance_of :terms_of_service, :on => :create
64 validates_confirmation_of :password, :email_address, :on => :create
65 end
db045db @dhh Initial
dhh authored
66
c4e5196 @dhh Updated documentation even more
dhh authored
67 {Learn more}[link:classes/ActiveRecord/Validations.html]
db045db @dhh Initial
dhh authored
68
69 * Callbacks as methods or queues on the entire lifecycle (instantiation, saving, destroying, validating, etc).
70
71 class Person < ActiveRecord::Base
72 def before_destroy # is called just before Person#destroy
73 CreditCard.find(credit_card_id).destroy
74 end
75 end
76
77 class Account < ActiveRecord::Base
78 after_find :eager_load, 'self.class.announce(#{id})'
79 end
80
c4e5196 @dhh Updated documentation even more
dhh authored
81 {Learn more}[link:classes/ActiveRecord/Callbacks.html]
db045db @dhh Initial
dhh authored
82
83
84 * Observers for the entire lifecycle
85
86 class CommentObserver < ActiveRecord::Observer
87 def after_create(comment) # is called just after Comment#save
c4e5196 @dhh Updated documentation even more
dhh authored
88 Notifications.deliver_new_comment("david@loudthinking.com", comment)
db045db @dhh Initial
dhh authored
89 end
90 end
91
c4e5196 @dhh Updated documentation even more
dhh authored
92 {Learn more}[link:classes/ActiveRecord/Observer.html]
db045db @dhh Initial
dhh authored
93
94
95 * Inheritance hierarchies
96
97 class Company < ActiveRecord::Base; end
98 class Firm < Company; end
99 class Client < Company; end
100 class PriorityClient < Client; end
101
c4e5196 @dhh Updated documentation even more
dhh authored
102 {Learn more}[link:classes/ActiveRecord/Base.html]
db045db @dhh Initial
dhh authored
103
104
aa4af60 @lifo Improve documentation.
lifo authored
105 * Transactions
db045db @dhh Initial
dhh authored
106
aa4af60 @lifo Improve documentation.
lifo authored
107 # Database transaction
db045db @dhh Initial
dhh authored
108 Account.transaction do
109 david.withdrawal(100)
110 mary.deposit(100)
111 end
112
c4e5196 @dhh Updated documentation even more
dhh authored
113 {Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
db045db @dhh Initial
dhh authored
114
115
116 * Reflections on columns, associations, and aggregations
117
118 reflection = Firm.reflect_on_association(:clients)
119 reflection.klass # => Client (class)
120 Firm.columns # Returns an array of column descriptors for the firms table
121
c4e5196 @dhh Updated documentation even more
dhh authored
122 {Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
db045db @dhh Initial
dhh authored
123
124
125 * Direct manipulation (instead of service invocation)
126
127 So instead of (Hibernate[http://www.hibernate.org/] example):
128
129 long pkId = 1234;
130 DomesticCat pk = (DomesticCat) sess.load( Cat.class, new Long(pkId) );
131 // something interesting involving a cat...
132 sess.save(cat);
133 sess.flush(); // force the SQL INSERT
134
135 Active Record lets you:
136
137 pkId = 1234
138 cat = Cat.find(pkId)
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
139 # something even more interesting involving the same cat...
db045db @dhh Initial
dhh authored
140 cat.save
141
c4e5196 @dhh Updated documentation even more
dhh authored
142 {Learn more}[link:classes/ActiveRecord/Base.html]
db045db @dhh Initial
dhh authored
143
144
145 * Database abstraction through simple adapters (~100 lines) with a shared connector
146
c21fdf3 @dhh Changed :dbfile to :database for SQLite adapter for consistency (old …
dhh authored
147 ActiveRecord::Base.establish_connection(:adapter => "sqlite", :database => "dbfile")
db045db @dhh Initial
dhh authored
148
149 ActiveRecord::Base.establish_connection(
150 :adapter => "mysql",
151 :host => "localhost",
152 :username => "me",
153 :password => "secret",
154 :database => "activerecord"
155 )
156
c4e5196 @dhh Updated documentation even more
dhh authored
157 {Learn more}[link:classes/ActiveRecord/Base.html#M000081] and read about the built-in support for
57b5fb4 @jeremy Correct rdoc link to OracleAdapter. Closes #5289.
jeremy authored
158 MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html], PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], SQLite[link:classes/ActiveRecord/ConnectionAdapters/SQLiteAdapter.html], Oracle[link:classes/ActiveRecord/ConnectionAdapters/OracleAdapter.html], SQLServer[link:classes/ActiveRecord/ConnectionAdapters/SQLServerAdapter.html], and DB2[link:classes/ActiveRecord/ConnectionAdapters/DB2Adapter.html].
db045db @dhh Initial
dhh authored
159
160
161 * Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
162
163 ActiveRecord::Base.logger = Logger.new(STDOUT)
164 ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")
165
166
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
167 * Database agnostic schema management with Migrations
168
169 class AddSystemSettings < ActiveRecord::Migration
170 def self.up
171 create_table :system_settings do |t|
8f46355 @jbarnette Killing/fixing a bunch of outdated language in the AR README.
jbarnette authored
172 t.string :name
173 t.string :label
174 t.text :value
175 t.string :type
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
176 t.integer :position
177 end
178
179 SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1
180 end
181
182 def self.down
183 drop_table :system_settings
184 end
185 end
186
187 {Learn more}[link:classes/ActiveRecord/Migration.html]
188
db045db @dhh Initial
dhh authored
189 == Simple example (1/2): Defining tables and classes (using MySQL)
190
191 Data definitions are specified only in the database. Active Record queries the database for
192 the column names (that then serves to determine which attributes are valid) on regular
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
193 object instantiation through the new constructor and relies on the column names in the rows
db045db @dhh Initial
dhh authored
194 with the finders.
195
196 # CREATE TABLE companies (
197 # id int(11) unsigned NOT NULL auto_increment,
198 # client_of int(11),
199 # name varchar(255),
200 # type varchar(100),
201 # PRIMARY KEY (id)
202 # )
203
204 Active Record automatically links the "Company" object to the "companies" table
205
206 class Company < ActiveRecord::Base
207 has_many :people, :class_name => "Person"
208 end
209
210 class Firm < Company
211 has_many :clients
212
213 def people_with_all_clients
214 clients.inject([]) { |people, client| people + client.people }
215 end
216 end
217
218 The foreign_key is only necessary because we didn't use "firm_id" in the data definition
219
220 class Client < Company
221 belongs_to :firm, :foreign_key => "client_of"
222 end
223
224 # CREATE TABLE people (
225 # id int(11) unsigned NOT NULL auto_increment,
226 # name text,
227 # company_id text,
228 # PRIMARY KEY (id)
229 # )
230
231 Active Record will also automatically link the "Person" object to the "people" table
232
233 class Person < ActiveRecord::Base
234 belongs_to :company
235 end
236
237 == Simple example (2/2): Using the domain
238
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
239 Picking a database connection for all the Active Records
db045db @dhh Initial
dhh authored
240
241 ActiveRecord::Base.establish_connection(
242 :adapter => "mysql",
243 :host => "localhost",
244 :username => "me",
245 :password => "secret",
246 :database => "activerecord"
247 )
248
249 Create some fixtures
250
251 firm = Firm.new("name" => "Next Angle")
252 # SQL: INSERT INTO companies (name, type) VALUES("Next Angle", "Firm")
253 firm.save
254
255 client = Client.new("name" => "37signals", "client_of" => firm.id)
256 # SQL: INSERT INTO companies (name, client_of, type) VALUES("37signals", 1, "Firm")
257 client.save
258
259 Lots of different finders
260
261 # SQL: SELECT * FROM companies WHERE id = 1
262 next_angle = Company.find(1)
263
264 # SQL: SELECT * FROM companies WHERE id = 1 AND type = 'Firm'
265 next_angle = Firm.find(1)
266
267 # SQL: SELECT * FROM companies WHERE id = 1 AND name = 'Next Angle'
7aa9eed @jeremy Deprecation: update docs. Closes #5998.
jeremy authored
268 next_angle = Company.find(:first, :conditions => "name = 'Next Angle'")
db045db @dhh Initial
dhh authored
269
270 next_angle = Firm.find_by_sql("SELECT * FROM companies WHERE id = 1").first
271
272 The supertype, Company, will return subtype instances
273
274 Firm === next_angle
275
276 All the dynamic methods added by the has_many macro
277
278 next_angle.clients.empty? # true
279 next_angle.clients.size # total number of clients
280 all_clients = next_angle.clients
281
282 Constrained finds makes access security easier when ID comes from a web-app
283
284 # SQL: SELECT * FROM companies WHERE client_of = 1 AND type = 'Client' AND id = 2
285 thirty_seven_signals = next_angle.clients.find(2)
286
287 Bi-directional associations thanks to the "belongs_to" macro
288
289 thirty_seven_signals.firm.nil? # true
290
291
292 == Philosophy
293
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
294 Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is
db045db @dhh Initial
dhh authored
295 object-relational mapping. The prime directive for this mapping has been to minimize
6ab9f2b @dhh Fix READMEs (closes #2680) [coffee2code]
dhh authored
296 the amount of code needed to build a real-world domain model. This is made possible
db045db @dhh Initial
dhh authored
297 by relying on a number of conventions that make it easy for Active Record to infer
298 complex relations and structures from a minimal amount of explicit direction.
299
300 Convention over Configuration:
301 * No XML-files!
302 * Lots of reflection and run-time extension
303 * Magic is not inherently a bad word
304
305 Admit the Database:
306 * Lets you drop down to SQL for odd cases and performance
307 * Doesn't attempt to duplicate or replace data definitions
308
309
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
310 == Download and installation
db045db @dhh Initial
dhh authored
311
f1082bd @josevalim Remove old install.rb files.
josevalim authored
312 The latest version of Active Record can be installed with Rubygems:
db045db @dhh Initial
dhh authored
313
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
314 % [sudo] gem install activerecord
db045db @dhh Initial
dhh authored
315
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
316 Source code can be downloaded as part of the Rails project on GitHub
db045db @dhh Initial
dhh authored
317
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
318 * http://github.com/rails/rails/tree/master/activerecord/
db045db @dhh Initial
dhh authored
319
320
321 == License
322
b3bfe13 @dhh Updated the license (still referered to the old ruby one)
dhh authored
323 Active Record is released under the MIT license.
db045db @dhh Initial
dhh authored
324
325
326 == Support
327
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
328 API documentation is at
db045db @dhh Initial
dhh authored
329
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
330 * http://api.rubyonrails.com
db045db @dhh Initial
dhh authored
331
89b5e79 @mislav revise download/installation/support sections in READMEs
mislav authored
332 Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
333
334 * https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets
Something went wrong with that request. Please try again.