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 は一応読めました。でも今日は駄目だ。