In Part 1 of this series, we looked at installing Rails, generating a new project and starting the server. We also took a quick look at the structure of a Rails project. But now let's make it do something, fast. By the end of this part, you should have a fully functional blog.
What is a Blog
Perhaps a silly question to be asking in this day and age, but what exactly is a blog? At its core, what data is needed to run a blog? Since Ruby on Rails applications are normally built iteratively (one of the core principles of agile development), all you need to implement to start out with is the very basic shell of the application. So, in this case, a blog is a collection of posts. A post is a title and a body and a date it was posted on. That's about it.
You'll also have to think about what types of data these fields should be represented as. There are two types of string data, analogous to the types of string data usually found in SQL databases: string (like a varchar) and text. String should be used for shorter strings, text for large blobs of text. As for the date, this is handled by Rails, so don't worry about specifying it.
So the basic structure of the model is this: there are a number of posts, each post has a string title and text body. That's all you really need to specify at this point.
Ruby on Rails has a number of "generators." A generator is a script that generates stub models, view and controllers. They're meant to give you something to start from, rather than coding a whole new controller from scratch (which, as it turns out, isn't difficult anyway but this just saves a lot of repetitive grunt work). The generator we're interested in is the "scaffold" generator, which in turn generates models, views, controllers and migrations.
To use the scaffold generator (and similarly other generators), we use the rails command line command from your project directory. The first argument to the command is the name of the script you want to run, in this case generate scaffold. This is a two part name, the scaffold script is a type of generator script. The scaffold script then takes the name of the model and controller you want to generate, in this case we're describing posts so we'll call it Post, and the names and types of the fields separated by colons. As discussed above, the fields we want are title:string body:text. So the complete command is rails generate scaffold Post title:string body:text. Running this will produce output similar to the output below.
Perusing the output you can see it generated a migration (more on that below), as well as the model, view and controller for the Post class. As you will see, these are functional but minimal, it didn't spit out a complete blog with a single command, just enough to be able to display and manipulate the Posts resource in a minimal way.
Iterative design of database-driven web applications can be difficult. Databases just weren't meant to be designed that way. SQL databases in particular we meant to be meticulously planned ahead of time. To get around this, Rails helps you manage your database tables with migrations. A migrations is a script that, when run, will add new tables to the database, or add columns to an existing table, or remove columns. When needed, any data you have that needs to be moved around as part of this operation can be done inside of a migration.
The scaffold script generated a migration for you in the db/migrate directory. The name of this file will differ (the first part of the filename is the time the file was generated), but it'll end in _create_posts.rb. Open this up in a text editor and you'll see a database-defining meta-language in Ruby. While it's certainly useful to learn this well, for now just see that it made a title string, text body and added the timestamps.
class CreatePosts < ActiveRecord::Migration def change create_table :posts do |t| t.string :title t.text :body t.timestamps end end end
But this is just the definition. The database we created in the previous part is still empty, so we need to run the migration first. To run all migrations and bring the database up to the latest spec, run the command rake db:migrate. The database table is ready to go. If your server is already running, close it and start a new one with rails server.
Getting Rid of the Start Page
If you open up http://localhost:3000/, you'll see that the Rails start page is still displayed. First delete the public/index.html file. If you don't delete this, it will override any request to the root of your web application. If you then visit the same URL, you'll get a Rails error saying No route matches [GET] "/". So we need to modify how the root URL is routed.
When a request is made to a Rails application, it first passes through the router. This router, configured with the file config/routes.rb, decides which controllers and actions are connected to which URLs. If you open this file now, you'll see a lengthy list of comments and only a single route installed, the resources :posts route that tells Rails about our Post resource. The comments are worth reading, they're a handy synopsis of how to write routes for various things. But right now we need to quickly add another route.
Routes are first see first follow. When a new request comes in, it goes down the list of routes and the first route that it matches if follows. So to make sure that your route for the root of the application takes priority, put it as the first line of the block (just above the existing resources line). The line you'll want to add is root :to => 'posts#index'. This is a convention you'll see often, a string with a controller and action separated by a hash mark. In this case, the posts controller with the index action. So when the root of the web application is accessed, we mean to access the index action of the posts controller. So your config/routes.rb file should now look like this (minus all the comments).
Blog::Application.routes.draw do root :to => 'posts#index' resources :posts end
Open up http://localhost:3000/ yet again and you'll see something very different. You'll see a page listing posts, a link to create new posts, forms to add them to the database, etc. Technically, it's a fully functional blog, if not formatted completely wrong. In the next part, we'll make this into something much more blog-like.