ActiveRecord is what is referred to as an Object-Relational Mapping. It's responsible for mapping exactly one row in a database to one object in Ruby. Its name refers to the Active Record Pattern identified by Martin Fowler in the 2003 book Patterns of Enterprise Application Architecture. It is a core part of Ruby on Rails and is responsible for handling all database interaction from the application level.
ActiveRecord maps a database row to an object in Ruby. What this means in practice is that you use ActiveRecord to create or retrieve your data and use traditional Ruby methods and attribute assignments to interact with this data. Instead of composing an SQL query manually, filling in the search parameters, sending it off to a database API, running the query, examining and parsing the result and storing the result in either a hash or a database, you let ActiveRecord do all that for you.
For example, say the web application in question is the blog. You display the latest blog entry on the front page, so you need to retrieve that entry first. Using an SQL statement, you'd compose an SQL query something like "SELECT * FROM posts ORDER BY date DESC LIMIT 1". That's quite the mouthful for what you really want to say, which is "get me the latest blog post." Using ActiveRecord, that query now becomes something like
p = Post.last. That's it, ActiveRecord knows what you want, composes the SQL query for you, submits it, parses the output and puts in a handy Ruby object for you to use. You can now refer to the post's title with method calls like p.title, assign to it using p.title = "A new title" and save it back to the database with p.save.
CRUD is an acronym meaning "Create, Read, Update, Delete," the four basic database operations. At its core, this is what ActiveRecord is meant to handle. Each is handled by a very idiomatic Ruby API, if you didn't know better you might not even know these are ActiveRecord objects, they're just normal Ruby objects after all.
- Create - To create an ActiveRecord object, simply instantiate it. If you have a Post model in your Rails application, call Post.new. Nothing special is needed to create a new ActiveRecord object. You can also call the create class method with a hash describing the object, for example Post.create(title:"A blog post", date:Time.now). Besides using the create method, it's up to you to fill in the data fields.
- Read - Reading refers to retrieving data from the database. ActiveRecord provides a whole host of methods for english-like queries. You can find the first or last object with method calls like Post.first or Post.last, but it also auto-generates a number of methods depending on the columns in the database. You can say things like Post.find_by_title("A blog post") or Post.find_by_id(7), each of these "find_by_" methods being automatically generated when ActiveRecord boots and examines the database tables.
- Update - Updating is as simple as reading an object from the database, changing something and calling the save method on it. Assuming you've retrieved a blog post and stored it in the variable p, you can do p.title = "A new title"; p.save.
- Delete - In order to delete an ActiveRecord object, you must call the destroy method. This will destroy the database row using a DELETE query, but keep the Ruby object intact. This may also destroy other database rows that are "owned" by this row, to keep data intact.
A relational database isn't much without tables cross-referencing each other. A post has a number of comments that belong to it, each comment in the database has a post_id column so they can be associated with a post. ActiveRecord takes care of these associations for you, abstracting them as sub-objects so again, you don't have to touch SQL here.
There are a few types of associations supported by ActiveRecord.
- belongs_to - Saying one type belongs_to another type implies that this type as the ID column referring to the other type. A comment on a blog post belongs_to the blog post. The comment table will have a column called post_id referring to the post it belongs to. If you have a comment object c, you can refer to the post that owns it as c.post. Since the comment is owned by the blog post, if you delete the post it will also delete the comment.
- has_many - This is the other end of the belongs_to relationship. A blog post has_many comments. The blog post doesn't maintain a list of comments that belongs to it, it simply queries the comments table for rows referring to the post. If you have a blog post p, the comments it owns are referred to as the array p.comments.
- has_one - This association is very similar to has_many, except only one is allowed to be owned by the object. A product in a catalog might only have one product manual, otherwise this is the same as the has_many association. If you try to assign more than one manual to the product, since it's a has_one association there will be an error.
- has_and_belongs_to_many - This is the most complex association. The classic example is a tagging system. If a blog post has a number of tags, it could has_many tags, it would be possible to search for blog posts with that tag. But since the tag can only refer to one blog post since the other end of a has_many association is a belongs_to association, a tag would only be able to refer to one blog post. In this case, a many-to-many association is handled using has_and_belongs_to_many (often referred to as habtm) is implemented using a "join table," a table that cross-references both the posts and the tags.
ActiveRecord also handles data integrity. It does this at a higher level than simply adding keys to database tables, it ensures that data is sane before saving to the database. Keeping these sanity checks at a lower level allows application code that uses these ActiveRecord objects from having to worry about the implications of setting a certain attributes.
In practice, data sanity is implemented in two ways. First, attribute assignment methods are often overridden to take care of housekeeping or data sync issues. For example, if I set a new password on a User object, this is where password hashing takes place. The application code doesn't know or care about the password hashing, it's done transparently by the model.
There's also a whole host of validation methods that must be checked before the object is saved or updated. For example, you can validate the presence of certain fields (a blog post cannot be submitted without a title), or the format of other fields (an IP address field must look like an IP address, or be in a certain block of IP addresses). This is an extremely powerful and flexible part of ActiveRecord, perhaps the best reason for using it in the first place. Placing very strict and stringent validations on your models can ensure that the database does not become corrupted by an application error. This is especially true since the application is operating on an abstracted form of the data, and the programmer may not be considering the implications of setting certain attributes.
Modern Ruby on Rails is a modular framework. Though the default ORM for Rails is ActiveRecord, and it's what most people use, you should be aware that there are others. DataMapper, for example, is a simpler ORM that's relatively popular. Depending on your application, you may choose this, an even smaller one, or even a custom ORM. Just be aware that ActiveRecord may be great, and the default, but there are other options.