Ruby on Rails Tutorial (3)

7.3 節以降とのことですがざっくり以下らしい。

  • 7.3.1 は Factory という gem
  • 7.3.2 は gravatar
  • 7.3.3 は named route

Factory という gem が出てきてますが fixture は使わないんですね。とりあえず 7.3.1 のみ実装してみます。
Gemfile の test な group に以下を追加。

  gem 'factory_girl_rails', '1.0'

で、bundle install するのか。

$ bundle install
// 略
Installing factory_girl (1.3.3) 
Using rdoc (3.9.1) 
Using thor (0.14.6) 
Using railties (3.0.9) 
Using rails (3.0.9) 
Installing factory_girl_rails (1.0) 
// 略
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
$

で、以下の内容で spec/factories.rb を作れば良いの?

# By using the symbol ':user', we get Factory Girl to simulate the User model.
Factory.define :user do |user|
  user.name                  "Michael Hartl"
  user.email                 "mhartl@example.com"
  user.password              "foobar"
  user.password_confirmation "foobar"
end

それから spec/controllers/users_controller_spec.rb に以下を追加か。

  describe "GET 'show'" do

    before(:each) do
      @user = Factory(:user)
    end

    it "should be successful" do
      get :show, :id => @user
      response.should be_success
    end

    it "should find the right user" do
      get :show, :id => @user
      assigns(:user).should == @user
    end
  end

これで spec 実行してみたらどうなるか。

$ bundle exec rspec spec/controllers/users_controller_spec.rb
....

Finished in 1.13 seconds
4 examples, 0 failures
$

わを。Green ですな。
以降をどうしようかな。一応盛り込みはしておく方向で。次の Chapter 8 は違う branch らしいのできちんと盛り込んで commit して merge しないと駄目だな。
とりあえずエントリ投入。

続き

spec/controller/users_controller_spec.rb の GET show なソレに以下を追加らしい。

  • it should have the right title
  • it should include the user's name
  • it should have a profile image
    it "should have the right title" do
      get :show, :id => @user
      response.should have_selector("title", :content => @user.name)
    end

    it "should include the user's name" do
      get :show, :id => @user
      response.should have_selector("h1", :content => @user.name)
    end

    it "should have a profile image" do
      get :show, :id => @user
      response.should have_selector("h1>img", :class => "gravatar")
    end

うーん、やっぱなんとなく話てきに本筋ではない気がしてならないので止めよ。で、Chapter 8 に突入しつつ、元気が無いのでガス欠になったら早めに休みます。

Chapter 8

の前に git を云々して modeling-users な branch を master に merge だん。でとりあえず DB をリセットせよ、とあります。

$ bundle exec rake db:reset
db/test.sqlite3 already exists
db/test.sqlite3 already exists
db/development.sqlite3 already exists
-- create_table("users", {:force=>true})
   -> 0.2987s
-- add_index("users", ["email"], {:name=>"index_users_on_email", :unique=>true})
   -> 0.1125s
-- initialize_schema_migrations_table()
   -> 0.2559s
-- assume_migrated_upto_version(20111012115230, "db/migrate")
   -> 0.3990s
$

次に branch をナニ。

$ git checkout master
Already on 'master'
$ git checkout -b signing-up
Switched to a new branch 'signing-up'
$

ここでいったん全体に目を通してみます。のでエントリ追加投入。

盛り込み

とりあえず get :new に以下な試験を追加らしい。

  • it should be successful
  • it should be have the right title

って、スデにありますね。app/views/users/new.html.erb に手を入れるのかどうか。現時点では以下ですね。

<h1>Users#new</h1>
<p>Find me in app/views/users/new.html.erb</p>

これを以下に、とのこと。

<h1>Sign up</h1>

<%= form_for(@user) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation, "Confirmation" %><br />
    <%= f.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

form_for というのがポイントなのか。rails3 からは記法が変更になったとかな記述がありますね。そして確かにここでは @user なナニが存在する前提だな。
それで controller な記述を以下に、とのことなのか。

  def new
    @user = User.new
    @title = "Sign up"
  end

うう、諸々をスルーしつつ登録処理にまで足が及んでます。以下な試験を追加らしい。
まず failure なソレからで

  • it should not create a user
    • フィールド全部空なのはダウト
  • it should have the right title
  • it should render the 'new' page
  describe "POST 'create'" do

    describe "failure" do

      before(:each) do
        @attr = { :name => "", :email => "", :password => "",
                  :password_confirmation => "" }
      end

      it "should not create a user" do
        lambda do
          post :create, :user => @attr
        end.should_not change(User, :count)
      end

      it "should have the right title" do
        post :create, :user => @attr
        response.should have_selector("title", :content => "Sign up")
      end

      it "should render the 'new' page" do
        post :create, :user => @attr
        response.should render_template('new')
      end
    end
  end

う、確かに記述の差が微妙に面白い。

        lambda do
          post :create, :user => @attr
        end.should_not change(User, :count)

        post :create, :user => @attr
        response.should render_template('new')

ですが、lambda で包むと実際に post しちゃって、そうでない下の記述であれば、new なテンプレが render されることを確認できる、のか。
あら、違うな。下側はエラーでもっかい new が render されるのか。なので以下な実装だよね、って案内があるはず。

  def create
    @user = User.new(params[:user])
    if @user.save
      # Handle a successful save.
    else
      @title = "Sign up"
      render 'new'
    end
  end

これで下二つの試験はパスしますね。あ、いっちゃん上のもパスするのか。あとエラーメセジの出力云々も AWDwR で見た記憶あり。
form_for なブロックに以下を仕込んでおいて

<%= form_for(@user) do |f| %>
  <%= render 'shared/error_messages' %>

app/views/shared/_error_messages..html.erb を以下にとのこと。

<% if @user.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@user.errors.count, "error") %> 
        prohibited this user from being saved:</h2>
    <p>There were problems with the following fields:</p>
    <ul>
    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

エラーがあれば云々、ということですね。素晴しい。あと、CSS に以下を追加しとけば幸せになれる云々な記述もありますがスルー。

.field_with_errors {
  margin-top: 10px;
  padding: 2px;
  background-color: red;
  display: table;
}

.field_with_errors label {
  color: #fff;
}

#error_explanation {
  width: 400px;
  border: 2px solid red;
  padding: 7px;
  padding-bottom: 12px;
  margin-bottom: 20px;
  background-color: #f0f0f0;
}

#error_explanation h2 {
  text-align: left;
  font-weight: bold;
  padding: 5px 5px 5px 15px;
  font-size: 12px;
  margin: -7px;
  background-color: #c00;
  color: #fff;
}

#error_explanation p {
  color: #333;
  margin-bottom: 0;
  padding: 5px;
}

#error_explanation ul li {
  font-size: 12px;
  list-style: square;
}

あと、8.2.4 もスルー。

ガス欠

8.3 Signup success は一応読めました。でも今日は駄目だ。