# Step-by-step demonstration

Get Version

2.3.0

In this demo we’ll create a blog; because that’s what blogs are for: being
demonstrations of web frameworks.

The demonstration uses new features of Rails 2.0 and the snippets in this bundle.

## A New App

    rails blog
    cd blog
    mate .

## Add some models

    ruby script/generate model Post subject:string body:text

This creates a 001_create_posts migration with a create_table:

    create_table :posts do |t|
      t.string :subject
      t.text :body

      t.timestamps
    end

## Sexy Migration support

If you put the cursor on the line after `t.text :body`, type `t.` and press &#x21E5;. Select “Create boolean column” (by pressing 0), and type “published” into the template field. If nothing happened when you pressed &#x21E5;, check that when you opened the migrations file you’ve selected the bundle “Ruby on Rails”.

Note that another `t.` was created on the next line! Press &#x21E5; and the cursor will be placed after it. You can now press &#x21E5; again to create another column, or delete this line.

Here, delete the extraneous `t.` line (&#x2303; &#x21E7; K). And save the file (&#x2318; S).

Run the migrations, either from the prompt:

rake db:migrate

or directly from the editor with &#x2303; | (Ctrl-Pipeline), and choosing option “Migrate to Current”.

## Post fixtures

Update the `test/fixtures/posts.yml` file as:

    published:
      subject: Some article
      body: A test article
      published: true

    nonpublished:
      body: Still writing this one

Note, in Rails 2.0 fixtures no longer have explicit ids. Later on we’ll look at snippets for using Foxy Fixtures with auto-completion for associations.

## Public blog controller

Create a controller for our blog, either via the command prompt:

ruby script/generate controller blog

or directly from the editor with &#x2303; |, and choosing option “Call Generate Script”, choose “Controller”, give it the name “blog”, and empty the list of actions.

Now open `blog_controller_test.rb`. To find this file quickly press &#x2318; T, type `bct`, and select the file.

Note how much cleaner functional tests are now via `ActionController::TestCase`.

Let’s do some TDD. First, delete the `test_truth` dummy method.

To create a test to show a list of blog articles:

deftg

and &#x21E5; gives:

    def test_should_get_action
      @model = models(:fixture_name)
      get :action, :id => @model.to_param
      assert_response :success

    end

Type `index` to replace `action`. Press &#x21E5;, and then &#x232B; to remove the first line, then press &#x21E5; three times and then &#x232B; to remove the `:id => @model.to_param` part. The press &#x21E5; again to go to the end of the method. Now we have:

    def test_should_get_index
      get :index
      assert_response :success

    end

Now type `asg`, press &#x21E5;, and type `posts`, and press &#x21E5; again. This creates an instance variable lookup within an assertion:

    assert(posts = assigns(:posts), "Cannot find @posts")

Now, let’s assert the HTML format.

Type `ass` and press &#x21E5;. Type `div#posts`, press &#x21E5; and &#x232B;, then &#x21E5; twice to place the cursor within the `assert_select` block:

    assert_select 'div#posts' do

    end

Now we’ll check that the `@posts` objects are represented in the `div#posts` element.

With the cursor inside the `assert_select`:

Type `ass`, press &#x21E5;, type `div.post`, press &#x21E5; twice, and type `count` (to replace the `text`). Now press &#x21E5; again, and type `posts.size`. Press &#x21E5; a final time (it will highlight the `do...end` block), and press &#x232B;.

Our test method is now finished:

    def test_should_get_index
      get :index
      assert_response :success
      assert(posts = assigns(:posts), "Cannot find @posts")
      assert_select 'div#posts' do
        assert_select 'div.post', :count => posts.size
      end
    end

NOTE: there is also a `deftp` snippet for functional tests to create a POST test stub.
To memorize: `deftg` stands for `define test get` and `deftp` stands for `define test post`

## Controller actions

To navigate to `blog_controller.rb` there are three options:

- press &#x21E7; &#x2325; &#x2318; &#x2193;, and select “Controller” from the drop-down list
- press &#x2325; &#x2318; &#x2193; and you’ll go directly to the controller (toggles between the two files)
- press &#x2318; T, type `bc`, choose the file, press &#x21A9;.

Add the `index` action method:

    def index
      @posts = Post.find_all_by_published(true)
    end

## Action views

To create/navigate to the view, press &#x21E7; &#x2325; &#x2318; &#x2193; and select “View” (like above). Or press &#x2325; &#x2318; &#x2193; to toggle between a controller method and it’s view.

As there are no `app/views/blog/index*` files, it will prompt you to create a blank view file. By default it guesses `index.html.erb` (because the method was named `index`), but of course you can change that in the dialog box.

If instead you got the message “blog_controller.rb does not have a view”, note that you first need to save the controller file before hitting &#x21E7; &#x2325; &#x2318; &#x2193; or &#x2325; &#x2318; &#x2193;. Also note that the cursor must be within the scope of a method for &#x21E7; &#x2325; &#x2318; &#x2193; or &#x2325; &#x2318; &#x2193; to work.

Press enter to accept `index.html.erb`. You are taken to the new file.

Let’s create HTML to match the earlier tests.

Type `div` and press &#x21E5; twice, then type `posts` and press &#x21E5;:

    <div id="posts">

    </div>

Inside the `div` element, type `for` and press &#x21E5;. This expands into a large ERb-enabled for-loop. Type `@posts`, press &#x21E5;, type `post` and press &#x21E5;. The cursor is now inside the for-loop.

Inside the for-loop, type: `div` and press &#x21E5;. Press &#x232B;, and type `class='post'` and press &#x21E5; to enter the `div` element.

Create a `<%= %>` element (&#x2303; >). If you press &#x2303; > again, it toggles to `<% %>`, and then again and it becomes `<%- -%>`, and again and it becomes `<%# %>` (a Ruby comment). Pressing &#x2303; > again starts at `<%= %>` again.

Enter `post.body` within the ERb template field.

Actually, we’ll need to show the subject too, so above the `<%= post.body %>` line (press &#x2191; followed by &#x2318; &#x21A9;)
type ‘h3’, and press &#x2303; < (LessThan), then &#x2303; > (GreatherThan), and `post.subject`.

The resulting line is: `<h3><%= post.subject %></h3>`

Move the cursor down between `<% else %>` and `<% end %>`.

Create a simple element `<p></p>` (&#x2303; &#x21E7; W or &#x2303; <). You can change the element type here. Just press &#x21E5; to go inside the element. Type `There are no posts available to read. All y'all come back soon, yer hear.` because its funny.

Our `index.html.erb` template is now:

    <div id="posts">
      <% if !@posts.blank? %>
        <% for post in @posts %>
          <div class="post">
            <h3><%= post.subject %></h3>
            <%= post.body %>
          </div>
        <% end %>
      <% else %>
        <p>There are no posts available to read. All y'all come back soon, yer hear.</p>
      <% end %>

    </div>

If we run our functional tests they now pass: run either from the command prompt with `rake test:functionals` or directly from the editor by pressing &#x2303; \ and press 2 for “Test Functionals”

As yet, we have no way for users to leave comments.

## Foxy Fixtures

Create a comment model:

ruby script/generate model Comment body:text name:string post:references

Note: here `post:references` is effectively the same as `post_id:integer`. Within the generated migration it creates `t.reference :post`. There is also a `t.` and `tcr` snippet for references, as for other standard datatypes, which helps setup polymorphic associations.

The generated `create_table` in `002_create_comments.rb` is:

    create_table :comments do |t|
      t.text :body
      t.string :name
      t.references :post

      t.timestamps
    end

Run `rake db:migrate`, or directly from the editor with &#x2303; | and choose option “Migrate to Current”.

Now create some comment fixtures so we can look at Foxy Fixtures. Open `text/fixtures/comments.yml` (&#x2318; T, type `cy`, press &#x21A9;).

By default, the generated `comments.yml` starts like:

    one:
      body: MyText
      name: MyString
      post:

    two:
      body: MyText
      name: MyString
      post:

The `post` fields replace the rails1.2 `post_id` fields. Now, we can specify the `post.yml` labels for a post. From above we have `published` and `unpublished`. It can be hard to remember what fixtures we have, so there is a key-combo helper.

Put the cursor after `post:` and press &#x2325; &#x238B;. A drop-down box appears with the names of the `posts.yml` fixtures. Select `published` and press &#x21A9;. Repeat for the 2nd fixture. This gives us:

    one:
      body: MyText
      name: MyString
      post: published

    two:
      body: MyText
      name: MyString
      post: published

## Associations

To enable the Foxy Fixtures, we need to add associations to the model classes.

You can now quickly go from a fixtures file (we’re in comments.yml) to the model file (&#x21E7; &#x2325; &#x2318; &#x2193;).

Within `comment.rb` model, create a new line within the class, and type `bt` and press &#x21E5;. Type `post`. This creates a snippet:

    belongs_to :post, :class_name => "Post", :foreign_key => "post_id"

The class name and foreign key are now generated from the association name. You can change them by tabbing across. But, we only need the default, so we can delete these options.

Press &#x21E5; and &#x232B; to remove the `:class_name` and `:foreign_key` options. The `Comment` class is now:

    class Comment < ActiveRecord::Base
      belongs_to :post
    end

Now go to the `Post` class. Press &#x2318; T and type `post` and select the model file, and press &#x21A9;.

Create a new line within the `Post` class (&#x2318; &#x21A9;). Type `hm` and press &#x21E5; to generate a `has_many` association. Type `comment`, and the resulting snippet is:

    has_many :comments, :class_name => "comment", :foreign_key => "class_name_id"

We don’t need the options. So press &#x21E5; once and then &#x232B;.

    class Post < ActiveRecord::Base
      has_many :comments
    end

Note: there is also a `has_many :through` snippet. Type `hmt` and &#x21E5; to activate it.

Finally, we can run our tests since adding the `Comment` model + fixtures (&#x2303; \).

    rake test

## Routes

Open the routes file (&#x2318; T, type `routes` and press &#x21A9;).

Change the routes file to:

    ActionController::Routing::Routes.draw do |map|
      map.resources :posts
      map.connect ':controller/:action/:id'
      map.connect ':controller/:action/:id.:format'
    end

## Creating Posts

From the `Post` model class (`post.rb`) you can now quickly navigate to a controller
of the same name. It supports either singular or plural controller names, but
will default to the plural name, which is the REST/resources preferred name.

To create a `PostsController`, use the ‘Go To’ hot key (as above) &#x21E7; &#x2325; &#x2318; &#x2193; and select ‘Controller’. As there is no `post_controller.rb` nor `posts_controller.rb` it will create a `posts_controller.rb` controller file; which is what we want here.

Note; at this stage you could use the Rails 2.0 `scaffold` generator to create the `posts_controller.rb` (and tests and routes).

In the blank file, we need to create a controller class.

Type `cla` and &#x21E5;, and select “Create controller class”. Type `Posts` and &#x21E5;,
`post` and &#x21E5;, and finally, `Post` and &#x21E5;. This leaves the cursor in the middle
of the generated class:

    class PostsController < ApplicationController
      before_filter :find_post

      private
      def find_post
        @post = Post.find(params[:id]) if params[:id]
      end
    end

## TDD for Posts controller

Currently there is not a functional test for our `posts_controller.rb`. To create it, use the ‘Go To’ hot key (&#x21E7; &#x2325; &#x2318; &#x2193;) and select ‘Functional Test’. This will create a blank file.

Type `cla` and &#x21E5;, and select “Create functional test class”.
Type `Posts` and &#x21E5;. (The functional test class name
should match the controller class, with `Test` suffixed to it).

The functional test class snippet gives you a `deft` stub. If you
press &#x21E5; now, it creates a generic test method snippet:

    def test_case_name

    end

Instead, we will use the `deftg` (GET request) and `deftp` (POST request) snippets.

Create a test for the `index`, `new` and `edit` actions. For `index` and `new`, we can delete the `@model = models(:fixture_name)`,
etc parts.

To test for the `create` action, type `deftp` and &#x21E5;. Type `create` and &#x21E5;, type `post` and &#x21E5;, type &#x232B; and &#x21E5;, and again &#x232B; and &#x21E5;. Now enter in a hash of the values to pass in for the test, say `:subject => 'Test', :body => 'Some body', :published => '1'`. The result should look like:

    def test_should_post_create
      post :create, :post => { :subject => 'Test', :body => 'Some body', :published => '1' }
      assert_response :redirect

    end

On the line after the `assert_response` expression, we’ll test
for where we want to be redirected to.

If you type `art` you create an old-style `assert_redirected_to :action => "index"`
snippet.

In addition there are now various `assert_redirected_to` snippets that
use resourceful routes:

- artp – `assert_redirected_to model_path(@model)`
- artpp – `assert_redirected_to models_path`
- artnp – `assert_redirected_to parent_child_path(@parent, @child)`
- artnpp – `assert_redirected_to parent_child_path(@parent)`

As we’ll see later, this naming scheme is used for other snippets that
use resourceful routes, like `link_to` and `redirect_to`.

Type `artpp` and &#x21E5;, and type `post`, to assert that the `create`
action must redirect to the index page.

The final `test_should_post_create` method is:

    def test_should_post_create
      post :create, :post => { :subject => 'Test', :body => 'Some body', :published => '1' }
      assert_response :redirect
      assert_redirected_to posts_path
    end

Running our tests (`rake test:functionals` or &#x2303; \) shows all these new tests failing.

## Views

Go back to the `posts_controller.rb` file (&#x2325; &#x2318; &#x2193;).

Now add three actions – `index`, `new` and `edit`. New methods can be created
with the `def` snippet:

    class PostsController < ApplicationController
      before_filter :find_post

      def index
        @posts = Post.find(:all)
      end

      def new
        @post = Post.new
      end

      def edit
      end

      private
      def find_post
        @post = Post.find(params[:id]) if params[:id]
      end
    end

Note: the `index` method could be created by typing `def`, &#x21E5;, `index`, &#x21E5;, `@posts = Post.fina`, &#x21E5;, &#x232B;.

Now we need templates for the `index`, `new` and `edit` actions.

Place the cursor inside the `index` method,
and use the ‘Go To’ hot key (&#x21E7; &#x2325; &#x2318; &#x2193;)
and select ‘View’. A dialog box will pop up asking for the name of the new
template (as there are no `app/views/posts/index*` files). By default, the
suffix is now `.html.erb` rather than the old `.rhtml`. Press &#x21A9;,
to accept `index.html.erb` as your template name.

Let’s just create a simple table showing the Posts.

Type `table` and &#x2303; < to generate `<table></table>`, and
press &#x21A9; to put the tags on separate lines.

Do the same to create a `<tbody></tbody>` element.

Inside the `<tbody></tbody>` we want to iterate over the `@posts`,
one per `<tr></tr>` row.

Press &#x2303; >, three times, to create a `<%- -%>` tag. Inside it
type `@posts.each do |post|`.

On the next line (&#x2318; &#x21A9;), type `end` and &#x21E5;, to create `<% end -%>`.
We now have a Ruby block within this ERb template.

Inside the block, create a `<tr></tr>` element, and within it
create a `<td></td>` element. We’ll skip over anything fancy
here, and just put the post’s subject here.

Type `post.subject` and select it. Now press &#x2303; > to wrap
the selected text inside `<%= post.subject %>`.

The resulting `index.html.erb` is:

    <table>
      <tbody>
        <%- @posts.each do |post| -%>
          <tr>
            <td><%= post.subject %></td>
          </tr>
        <% end -%>
      </tbody>
    </table>

## Forms

Place the cursor inside the `new` method,
and use the ‘Go To’ hot key (&#x21E7; &#x2325; &#x2318; &#x2193;)
and select ‘View’. Press &#x21A9; to accept `new.html.erb`.

Inside the blank `new.html.erb` file, type `ffe` and press &#x21E5;, and type `post`
and press &#x21E5; twice:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>

    <% end -%>

`form_for` is the Rails 2.0 preferred helper for managing forms, and
there are now snippets for common form_for helpers. There are `ff` and `ffe`
snippets; the former does not have the error messages section.

To create a label and text field for the `subject` attribute:

Create a `<p></p>` block (Press &#x2303; <, then &#x21E5;, then &#x21A9;).
Type `f.` and &#x21E5;, and select “Label”. Type `subject`, press &#x21E5; and press &#x232B;.
Create a `<br />` (&#x2303; &#x21A9;).
Type `f.` and &#x21E5;, and select “Text Field”. Type `subject`.

This gives us:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>
      <p>
        <%= f.label :subject %><br />
        <%= f.text_field :subject %>
      </p>
    <% end -%>

Now repeat for `body` and `published` fields.

Note, for `published`, you might change the label to `Published yet?` by tabbing
into the default string file.

Finally, add a “Submit” button using the `f.` snippet tab completion.

Start `script/server` from the prompt and you can now view this form at [http://localhost:3000/posts/new](http://localhost:3000/posts/new)

The final form is:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>
      <p>
        <%= f.label :subject %><br />
        <%= f.text_field :subject %>
      </p>
      <p>
        <%= f.label :body %><br />
        <%= f.text_area :body %>
      </p>
      <p>
        <%= f.label :published, "Published yet?" %><br />
        <%= f.check_box :published %>
      </p>
      <p>
        <%= f.submit "Submit" %>
      </p>
    <% end -%>

Note: if you got `<br>` when hitting &#x2303; &#x21A9; instead of `<br />` then you might want to go to the preferences of TextMate (&#x2318; ,), choose tab “Advanced”, choose “Shell Variables”, click the + sign to add a new shell variable, and give it the name `TM_XHTML` and a value of `/`

## Partials

The form we just created is exactly the same as the form required for the `edit.html.erb` template.

Instead of copy+pasting it into the `edit.html.erb` file, we’ll create a partial
template.

Select the entire form (&#x2318; A), and press &#x2303; &#x21E7; H and a dialog box appears.
Type in `form` and press &#x21A9;.

You’ll notice a new file `_form.html.erb` has appeared which contains the code you had selected,
while the code in the file `new.html.erb` has been replaced by:

<%= render :partial => ‘form’ %>

Now copy and paste this into the `edit.html.erb` file. To create this file,
return to the controller (from the `new.html.erb` file, press &#x2325; &#x2318; &#x2193;), go to the `edit` action,
and use &#x2325; &#x2318; &#x2193; again to create the `edit.html.erb` template file.

## Link helpers

At the bottom of the `new.html.erb` we want a link back to the list of all posts
(within the posts controller, not the public blog controller). This
will be the `index` action, and will be accessible via the resources route
`posts_path`.

There are several `link_to` snippets that support the resources routes:

- lip – `<%= link_to "link text...", model_path(@model) %>`
- lipp – `<%= link_to "link text...", models_path %>`
- linp – `<%= link_to "link text...", parent_child_path(@parent, @child) %>`
- linpp – `<%= link_to "link text...", parent_child_path(@parent) %>`
- lim – `<%= link_to model.name, model_path(model) %>`

The tab stop points are in useful places.

So, to create our link to the posts page, type `lipp` and &#x21E5;, type
`Show all posts`, press &#x21E5; twice and type `post`.

## Controllers: `respond_to` and `redirect_to`

Now we’ll add a `create` action to the `posts_controller.rb`. Let’s go there (&#x2325; &#x2318; &#x2193;).

Below the `edit` method type `def` and &#x21E5;, and type
`create` and &#x21E5;. Now fill out the `create` action like:

    def create
      @post = Post.new(params[:post])
      if @post.save

      else

      end
    end

Place the cursor in the `true` section of the `if` statement.
Type `repp` and &#x21E5; to create a `redirect_to` expression. Press &#x21E5;
again and replace the selected text with `post`.

Like the various `link_to` snippets, there are matching `redirect_to`
snippets.

- rep – `redirect_to(model_path(@model))`
- repp – `redirect_to(models_path)`
- renp – `redirect_to(parent_child_path(@parent, @child))`
- renpp – `redirect_to(parent_child_path(@parent))`

There are tab stops in useful places.

In the `false` section of the `if` expression, we’ll demonstrate the
`respond_to` block. There are two ways to generate a `respond_to` block.

Type `rest` and &#x21E5;, and you get a standard empty block you can work with:

    respond_to do |wants|
      wants.html {  }
    end

Press &#x21E5; twice to get inside the `wants.html` block, type `ra`, press &#x21E5;, then type `new`. The final block is:

    respond_to do |wants|
      wants.html { render :action => "new" }
    end

Alternately, there is the “upgrade” hot key (&#x21E7; &#x2318; H), where you can convert some
existing selected code, into a `respond_to` block.

Select the whole line containing the `redirect_to` expression from the
`true` section of the `if` statement (&#x21E7; &#x2318; L).

Press &#x21E7; &#x2318; H and the line is replaced with:

    respond_to do |wants|
      wants.html do
        redirect_to(posts_path)
      end
      wants.js {  }
    end

The `js` is the first tab stop. The point of this hot key is to instantly
refactor your existing html respond code, and support a second response
format.

For now remove the line with `wants.js` (&#x2303; &#x21E7; K).

The completed `create` action is:

    def create
      @post = Post.new(params[:post])
      if @post.save
        respond_to do |wants|
          wants.html do
            redirect_to(posts_path)
          end
        end
      else
        respond_to do |wants|
          wants.html { render :action => "new" }
        end
      end
    end

Yes you’d probably only have one `respond_to` block, but this is a
demo so I am taking the scenic route.

## Our application so far

In the browser, we can create posts via [http://localhost:3000/posts/new](http://localhost:3000/posts/new)
and then view them as a blog visitor at [http://localhost:3000/blog](http://localhost:3000/blog).

## Some more migrations

We’re looking for the following additions:

- rename the column `name` of table `comments` to `author`
- add a new column `author_url` to table `comments`
- add an index to the column `post_id` of the `comments` table

Let’s try to do this all in one migrations file. Start Quick Migration (&#x2303; &#x21E7; M). Let’s name it `ModifyComments`. A new migrations file `003_modify_comments.rb` is created and opened, and the cursor is placed behind the `mtab` trigger. For now delete `mtab` and instead enter `mcol` and press &#x21E5;. Choose `Rename / Rename Column` (3). Type `comments` &#x21E5; `name` &#x21E5; `author` &#x21E5; &#x21A9;.

Again type `mcol` and &#x21E5;. This time choose `Add / Remove Column` (1). Type `comments` &#x21E5; `author_url`, then &#x21E5; twice, and press &#x21A9;.

Now type `mind` and &#x21E5;. Choose `Add / Remove Index` (1). Type `comments` &#x21E5; `post_id`.

The end result looks like this:

    class ModifyComments < ActiveRecord::Migration
      def self.up
        rename_column :comments, :name, :author
        add_column :comments, :author_url, :string
        add_index :comments, :post_id
      end

      def self.down
        remove_index :comments, :post_id
        remove_column :comments, :author_url
        rename_column :comments, :author, :name
      end
    end

Notice how the `down` method calls are in reversed order of the `up` method calls.

Save the file (&#x2318; S) and migrate to current (&#x2303; |).

Be sure to modify the comments fixture file. Go there (&#x2318; T, press `cy`, choose `comments.yml`). Rename `name` to `author` and add a row for `author_url` for each comment. Check your tests again (&#x2303; \, choose option 1). All tests should pass.

Futhermore we’d like to know when a post was published. To do this we’ll want the following modifications:

- keep track of the datetime when a post was published.
- remove the column published from the posts table because it can be determined if a post is published by looking at whether or not a value is present for the published date.

Start Quick Migration (&#x2303; &#x21E7; M). Let’s name it `AddPublishedAtForPosts`. A new migrations file `004_add_published_at_for_posts.rb` is created and opened, and the cursor is placed behind the `mtab` trigger. Again delete `mtab` and instead enter `mcol` and press &#x21E5;. Choose `Add / Remove Column` (1). Type `posts` &#x21E5; `published_at` &#x21E5; `datetime` &#x21E5; and &#x21A9;.

Again type `mcol` and &#x21E5;. Choose `Remove / Add Column` (5). Type `posts` &#x21E5; `published` and press &#x21E5; twice.

The end result looks like this:

    class AddPublishedAtForPosts < ActiveRecord::Migration
      def self.up
        add_column :posts, :published_at, :datetime
        remove_column :posts, :published
      end

      def self.down
        add_column :posts, :published, :boolean
        remove_column :posts, :published_at
      end
    end

Notice how the `Remove / Add Column` command automagically determined in the `down` method the column type of column `published` to be a `boolean`. It determines this by looking at the current state of your `db/schema.rb` file.

Save the file (&#x2318; S) and migrate to current (&#x2303; |).

Now we need to modify the posts fixtures file. Go there (&#x2318; T, type `pyml`, choose `posts.yml`). Replace the line `published: true` by `published_at: 2008-1-1`.

Modify the posts functional test, first go there (&#x21E7; &#x2325; &#x2318; &#x2193;, choose “Go to Functional Test”). Replace `:published => '1'` by `:published_at => Date.new(2008, 1, 1)`.

Modify the post model, first go there (&#x21E7; &#x2325; &#x2318; &#x2193;, choose “Go to Model”). Have the code look like:

    class Post < ActiveRecord::Base
      has_many :comments

      def published
        !self.published_at.nil?
      end

      def published=(publish)
        if publish
          self.published_at = DateTime.now if self.published_at.nil?
        else
          self.published_at = nil
        end
      end
    end

Modify the `blog_controller.rb` file. Replace `Post.find_all_by_published(true)` by `Post.find(:all, :conditions => "published_at IS NOT NULL")`.

Finally, check your tests again (&#x2303; \). All tests should pass.

# TODO

- Model snippets (validates_…)
- link_to(model) (ltm)
- RJS demo

Dr Nic Williams, 7th June 2008
Theme extended from Paul Battley