7.2. Rails by Example The best way to understand Rails is to see it in action. Go to http://rubyforge.org and download Ruby and RubyGems . (If you use the Windows one-click installer, you'll get RubyGems with that distribution.) If you don't already have one, download a relational database manager, too. I used MySQL. You'll begin to get the Rails experience at install time. RubyGems lets you install Ruby applications and their dependencies. At the command line, type: gem install rails -v 0.12.1 Ruby will start the installation process. It goes up to RubyForge (rubyforge.org) and pulls down an index including the appropriate version of Rails and its dependencies. If you were to omit the version number, Ruby would get you the latest stable version. RubyGems will then prompt you for each dependency. Answer "Y," or answer "a" once for all dependencies: Attempting remote installation of 'rails' Updating Gem source index for: http://gems.rubyforge.org Install required dependency rake? [Yn] Y Install required dependency activesupport? [Yn] Y Install required dependency activerecord? [Yn] Y Install required dependency actionpack? [Yn] Y Install required dependency actionmailer? [Yn] Y Install required dependency actionwebservice? [Yn] Y Successfully installed rails, version 0.12.1 You'll notice that RubyGems will then attempt to build the documentation for each of the subcomponents and Rails. And that's it. Rails is installed. You're already getting hints about the approachability of Rails. 7.2.1. Generating a Basic Application You can now generate a Rails project. Go to your working directory and ask Rails to generate a project called trails: rails trails Ruby creates a full directory structure that will contain your application. There's no guesswork, and all Rails projects will have a consistent format. I'll point out a few important directories: app This directory has your application code. You'll see a directory for each component of MVC and a couple of others. config This directory will be very light. You'll put in anything that needs special configuration, like the connection parameters for your database. Since Ruby makes excellent use of defaults, your config directory will stay sparse. script Your trails app comes with scripts that will help you generate code, and start your application server. You'll notice a few other goodies as well, but for now, let's use one of the scripts to start Ruby's application server. Change to the trails directory, and type: ruby script/server If things are working, you'll see a server started on port 3000. You can go to http://127.0.0.1:3000/ to make sure things are running. You'll get a Rails welcome message. You just started a development Ruby web server, configured for Rails. If you need to change some properties of the server, you'll just change the script/server script. Notice that Ruby programmers typically do configuration, like this server script, in Ruby scripts. You've already learned that Ruby handles structured data well, without XML. For example, this is the part of the server script that has the configuration options: OPTIONS = { :port => 3000, :ip => "0.0.0.0", :environment => "development", :server_root => File.expand_path(File.dirname(_ _FILE_ _) + "/ /public/"), :server_type => WEBrick::SimpleServer } This code simply defines a hash map called OPTIONS. The => operator maps keys on the lefthand side to values on the right. Nothing has really happened yet, but you should be paying attention. You've set up a whole lot of infrastructure in a very short time. Our trails project will collect descriptions of mountain bike trails. We'll start simple, collecting an ID to go with a trail name, description, and difficulty. You'll type the field names once. The Rails metaprogramming features will read the columns from the database and dynamically add properties to your model objects. If you're using MySQL, you can fire up the mysql command processor. Create a database called trails and switch to it. Now, create a table called TRails: mysql> CREATE TABLE trails ( -> id int(6) NOT NULL auto_increment, -> name varchar(20), -> description text, -> difficulty varchar(20), -> primary key (id)); Query OK, 0 rows affected (0.36 sec) Notice the names. They are important. By convention, if you're working with more than one row (as in a table or a list), the name should be a plural. A column or class that refers to a singular object should be singular. Rails is smart enough to translate English plurals, so it knows to create a model called Person for a table called people. Watch the capitalization in these examples, too. It's important. If you follow Rails conventions with your names, you can just stay with Rails defaults, and your code will be much more concise. You'll need to tell Rails where to find your database. Edit config/database.yml to look like this: development: adapter: mysql database: trails host: localhost username: root password: password Stop and restart the server. (You only have to do so when you change your database configuration.) Let's generate a simple model. In the trails directory, simply type: ruby script/generate model trail Rails generates the model, some helper files, tests, and fixtures. For example, you can take a look at the model. Edit the file at app/models/trail.rb: class Trail < ActiveRecord::Base end That certainly looks anticlimactic. It looks like you'll simply type custom code here, in hopes that Rails will generate the rest of the code somewhere else. But that's not what happens at all. At runtime, Rails will load the ActiveRecord base class. Rails will look at the name of the class and load the definition of a table called trails. Then, it will dynamically add attributes, getters, setters, and database access methods to the trail base class! So, there's a lot more than meets the eye. One of the scripts that Rails generates lets you manipulate your model from an irb session. Type: ruby script/console You can now easily manipulate your model. For example, you can say: Trail.new do |trail| trail.name="Walnut Creek" trail.description="Meandering trail in Austin park" trail.difficulty="hard" trail.save end Now, you'll need a controller. You can generate that, too: ruby script/generate controller trails ruby script/generate model trails You just created the model and a default controller in app/controllers/trails_controller.rb for a collective page of trails. When you edit it, the controller is empty. Make it look like this: class TrailsController < ApplicationController def index render_text "This will be a trail someday " end end Point your browser to the URL http://localhost:3000/trail. You'll see your message printed. Of course, you didn't learn Rails to print strings, so change your controller to this: class TrailsController < ApplicationController scaffold :trails end scaffold is a method. The first parameter is :trails, a literal pointing to the TRails class. Save it, and load the same URL. Now, that's more interesting. You see a listing of trails. Click on the new trail link on the bottom. That's beyond interesting! You'll get a form like the one shown in Figure 7-1. You can see that the metaprogramming framework is working overtime. The scaffold method inferred the properties of the database and propagated them through the model and up to the user interface. You'll see exactly what goes into a scaffold controller later, but trust the magic for now. 7.2.2. Managing Relationships and Updating Views A list of trails will not get you very far by itself. It's the interactions between objects that gets difficult. Say you want to access trails by their city. The first job is to generate the model for locations. First you'll need a database table: mysql> CREATE TABLE locations ( -> id int(6) NOT NULL auto_increment, -> city varchar(20), -> state varchar(20), -> primary key (id)); Query OK, 0 rows affected (0.35 sec) Instead of dynamically generating the scaffolding, you can simultaneously generate the source code for the controller, and view, complete with scaffolding with ruby script/generate scaffold locations. Build the model for a single location with ruby script/generate model location. While you're at it, just to get a better look at what's going on behind the curtains, do the same for trail with ruby script/generate scaffold trails. Look at what you've done by pointing your browser to http://localhost:3000/locations. Make sure it works, and add a few locations. I'm . prompt you for each dependency. Answer "Y," or answer "a" once for all dependencies: Attempting remote installation of 'rails' Updating Gem source index for: http://gems.rubyforge.org. gem install rails -v 0.12.1 Ruby will start the installation process. It goes up to RubyForge (rubyforge.org) and pulls down an index including the appropriate version of Rails and its dependencies projects will have a consistent format. I'll point out a few important directories: app This directory has your application code. You'll see a directory for each component of MVC and