Rails Developers do it with Models
I saw a t-shirt at Mountain West RubyConf this year that said “Rails Developers do it with Models.” Of course, they were talking about the classes we use to access the database. In fact, in Ruby on Rails, when you think of your data, you usually think of Models, not the database. The database is more a mechanism for remembering the data when you’re not using it.
Let’s look at one of the files that were generated in Part I. This file is where the model for our blog’s posts are defined.
vim app/models/post.rb
class Post < ActiveRecord::Base end
You can see from our post.rb file that the Post class inherits from ActiveRecord::Base, which provides all of the methods we’ll need to manage our data. Let’s run quickly through the basics.
Creating New Data
There are two methods for creating new ActiveRecord objects from our Models: new and create. The difference between the two is that create validates the data in the model and saves it to the database if the object’s data is valid. The arguments for these methods come in a hash that describes the object’s attributes. Here’s an example:
post = Post.new(:title => "Creating a new post", :content => "Enter the data and then press the submit button")
This code above creates a new Post object which exists in memory, but is not saved to the database. If you need to save an in-memory object to the database, all you need to do is call the save method on the object.
post = Post.new post.title = "Here's another post" post.content = "Yeah, I seem to be creating a lot of these" post.save
Finding Existing Data
Once we’ve added some data to the database, ActiveRecord provides us with some terrific functionality for finding the data we want. We do this with the find method. For right now, we’re going to use simple examples. We’ll get into joining up with other types of data when we talk about ActiveRecord associations.
Let’s say, for example, that we want to find the post with the title “Here’s another post”
post = Post.find(:first, :conditions => "title = 'Here's another post'")
The first parameter, in this case :first, tells ActiveRecord which type of search we’re doing. In this case, it tells it to find the first post in the database that matches the conditions. The :conditions key in this case contains a string which forms the WHERE clause in the SQL statement sent to the database.
Of course, ActiveRecord makes it even easier than that. You could also perform the query this way:
post = Post.find(:first, :conditions => {:title => "Here's another post"})
This method is nice because we don’t have to form our SQL syntax.
Another search we can do is to find the last 5 posts written.
posts = Post.find(:all, :limit => 5,rder => "created_at DESC")
The created_at field was created by the t.timestamps method call in the migration.
In this case, the :all parameter indicates that our Model should return an array of Posts. :limit is the maximum number of Posts to return. In this case it returns the first five. rder is the ‘ORDER BY’ clause for the SQL query that find forms.
ActiveRecord also provides us with custom find methods for each of the model’s attributes.
Post.find_by_id(1) Post.find_by_title("Here's another post")
I’ll let you explore these on your own.
Updating Existing Data
There are three main ways of updating existing data. They are update_attributes, write_attribute, and assignment with =.
First, update_attributes is probably the most commonly used updating method in Ruby on Rails. This is because when we collect data in an html form to update an object, it usually comes grouped together in a Hash. The Hash’s keys correspond to the objects attributes. The Hash’s values correspond to the new value for the attribute that is its key.
# This is the hash with the new attributes. new_attributes = {:title => "Just one post", :content => "What do you mean, 'Just one post?' I'm certain there will be more than one!"} # This is the object we're going to update. post = Post.find_by_title("Here's another post") post.update_attributes(new_attributes) post.title # Returns "Just one post" post.content # Returns "What do you mean, 'Just one post?' I'm certain there will be more than one!"
The next most common is probably the = assignment as seen with the new Posts. This code snippet will effect the same changes as the previous code snippet.
# This is the hash with the new attributes. new_attributes = {:title => "Just one post", :content => "What do you mean, 'Just one post?' I'm certain there will be more than one!"} # This is the object we're going to update. post = Post.find_by_title("Here's another post") post.title = "Just one post" post.content = "What do you mean, 'Just one post?' I'm certain there will be more than one!" # Remember that 'save' perpetuates the these changes to the database. post.save post.title # Returns "Just one post" post.content # Returns "What do you mean, 'Just one post?' I'm certain there will be more than one!"
Finally, the method I like a little more than the = assignment: write_attribute. I like it better primarily because it saves me the trouble of calling save to write my changes to the database. Here’s a code snippet like the others.
# This is the hash with the new attributes. new_attributes = {:title => "Just one post", :content => "What do you mean, 'Just one post?' I'm certain there will be more than one!"} # This is the object we're going to update. post = Post.find_by_title("Here's another post") post.write_attribute(:title, "Just one post") post.write_attribute(:content, "What do you mean, 'Just one post?' I'm certain there will be more than one!") post.title # Returns "Just one post" post.content # Returns "What do you mean, 'Just one post?' I'm certain there will be more than one!"
In the next tutorial, I’m going to cover data relationships and deleting records. The reason I’ve grouped these together is because I want to cover when and when not to remove related records.