The ticket

Issue #1 in your copy of web-apps-2:

Post a taco
As a Tacostagram user, I want to post a photo of my tacos with a caption, so everyone can see what I'm eating.

Definition of done

  • The new post page shows a form with fields for the author, the body and the image.
  • Submitting the form creates a post with the author, body and image that were entered.
  • After submitting, the user lands on the posts page and sees the new post there.

The ticket is the whole specification. Your agent read it, built it, and wrote one test per sentence. Yours will not match this line for line, and should not. What should match is the shape: two actions, one form, three tests, and a pull request that a classmate reviewed against the ticket.

What the agent built

The controller

new and create were already there as comments. The agent filled them in, keeping each step comment:

def new
  # render posts/new view, the form for a new Post
  render({ :template => "posts/new" })
end

def create
  # start with a new Post
  post = Post.new
  # assign the form's values to the Post's columns
  post["author"] = params["author"]
  post["body"] = params["body"]
  post["image"] = params["image"]
  # save the Post row
  post.save
  # redirect the user
  redirect_to("/posts")
end

new only renders the form. create has no view: it saves and sends the user to a page that already exists. The three keys in params are the three name attributes in the form below.

The form

app/views/posts/new.html.erb had a skeleton with a comment where the fields go:

<h1>New post</h1>

<form action="/posts" method="post">
  <p>
    <label for="author">Author</label>
    <input type="text" name="author" id="author">
  </p>
  <p>
    <label for="body">Body</label>
    <input type="text" name="body" id="body">
  </p>
  <p>
    <label for="image">Image</label>
    <input type="text" name="image" id="image">
  </p>
  <button>Post it</button>
</form>

<p><a href="/posts">Back to all posts</a></p>

action="/posts" and method="post" are the create row of the pattern. No routes were added: resources("posts") in config/routes.rb already made all seven.

The tests

One per sentence, named with the sentence, in test/integration/posts_page_test.rb:

require "test_helper"

class PostsPageTest < ActionDispatch::IntegrationTest
  test "The new post page shows a form with fields for the author, the body and the image." do
    get("/posts/new")

    assert_response(:success)
    assert_select("form[action='/posts'][method='post']") do
      assert_select("input[name='author']")
      assert_select("input[name='body']")
      assert_select("input[name='image']")
    end
  end

  test "Submitting the form creates a post with the author, body and image that were entered." do
    post("/posts", :params => {
      "author" => "Ben",
      "body" => "Al pastor on a Tuesday",
      "image" => "https://images.unsplash.com/photo-tacos"
    })

    created = Post.find_by({ "author" => "Ben" })
    assert_not_nil(created)
    assert_equal("Al pastor on a Tuesday", created["body"])
    assert_equal("https://images.unsplash.com/photo-tacos", created["image"])
  end

  test "After submitting, the user lands on the posts page and sees the new post there." do
    post("/posts", :params => {
      "author" => "Ben",
      "body" => "Al pastor on a Tuesday",
      "image" => "https://images.unsplash.com/photo-tacos"
    })

    assert_redirected_to("/posts")
    follow_redirect!
    assert_select("h3", "Ben")
    assert_select("p", "Al pastor on a Tuesday")
    assert_select("img[src='https://images.unsplash.com/photo-tacos']")
  end
end
bin/rails test
3 runs, 21 assertions, 0 failures, 0 errors, 0 skips

Read each test against its sentence. The first fetches the form page and looks for the three inputs. The second submits the form and looks the row up in the table. The third submits, follows the redirect, and looks for the post on the page. Each one checks exactly what its sentence says, and nothing it doesn't.

Reviewing it

The five questions from class, answered for this change:

  1. Does it do what the issue says? The three sentences are the three tests, and they pass.
  2. Does the commit message tell you what changed? Yours to judge. "Add the new post form and create action, with tests" would.
  3. Does it follow the pattern? new and create in PostsController, the form posts to /posts, create redirects. Yes.
  4. A test per sentence, passing when you run them? Three sentences, three tests, green.
  5. Would you merge it? Yes. One thing you might ask for: the image is a text box the user has to paste an address into. That is what the ticket asked for; a file upload is week ten.

Issue #2, if you got to it

"Add a contact to a company" is the same loop with one new piece: the company's id has to travel from the company's page, through the form, to create, without the user typing it. That is a hidden field, and the "Handling relationships" section of Creating new records walks through it.