Ruby on Rails Tutorial (8)
ちょっとフライングで前の晩から着手してますが。
7.2 Signup form
とりあえずデータベースをリセットとのこと。
$ bundle exec rake db:reset $ bundle exec rake db:test:prepare
7.2.1 Tests for user signup
とりあえず以下な試験が fail なことを確認してみます。
spec/requests/user_pages_spec.rb
require 'spec_helper' describe "User pages" do subject { page } . . . describe "signup" do before { visit signup_path } let(:submit) { "Create my account" } describe "with invalid information" do it "should not create a user" do expect { click_button submit }.not_to change(User, :count) end end describe "with valid information" do before do fill_in "Name", with: "Example User" fill_in "Email", with: "user@example.com" fill_in "Password", with: "foobar" fill_in "Confirmation", with: "foobar" end it "should create a user" do expect { click_button submit }.to change(User, :count).by(1) end end end end
で、試験実行。
$ bundle exec rspec spec/request/
試験 red を確認。上書きしてなくて green 確認したのはヒミツ。
Failures: 1) User pages signup with invalid information should not create a user Failure/Error: expect { click_button submit }.not_to change(User, :count) Capybara::ElementNotFound: no button with value or id or text 'Create my account' found # (eval):2:in `click_button' # ./spec/requests/user_pages_spec.rb:30:in `block (5 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:30:in `block (4 levels) in <top (required)>' 2) User pages signup with valid information should create a user Failure/Error: fill_in "Name", with: "Example User" Capybara::ElementNotFound: cannot fill in, no text field, text area or password field with id, name, or label 'Name' found # (eval):2:in `fill_in' # ./spec/requests/user_pages_spec.rb:36:in `block (4 levels) in <top (required)>'
ふむ。成程。
7.2.2 Using form_for
app/views/users/new.html.erb を以下にとのこと。
<% provide(:title, 'Sign up') %> <h1>Sign up</h1> <div class="row"> <div class="span6 offset3"> <%= form_for(@user) do |f| %> <%= f.label :name %> <%= f.text_field :name %> <%= f.label :email %> <%= f.text_field :email %> <%= f.label :password %> <%= f.password_field :password %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation %> <%= f.submit "Create my account", class: "btn btn-large btn-primary" %> <% end %> </div> </div>
これを盛り込んで試験実行してみます。以下な方法が提示されています。
$ bundle exec rspec spec/requests/user_pages_spec.rb -e "signup page"
試験 red 終了。controller にも盛り込みが必要な模様。確かに new なアクションは空ですね。
def new @user = User.new end
これで試験を再度実行してみると green 終了してました。むむむ。
app/assets/stylesheets/custom.css.scss に以下を盛り込んで次の項に進みます。
/* forms */ input, textarea, select, .uneditable-input { border: 1px solid #bbb; width: 100%; padding: 10px; margin-bottom: 15px; @include box_sizing; } input { height: auto !important; }
一応、見栄えがどうかを確認しようと思ったのですが、突如端末が暴走。再起動して WEBrick 起動して確認してみました。結構無茶な使い方してるはずなのでアレ。
/signup と /users/new の違いは何なのか別途確認。
あと WEBrick は使わないときはオトしておかないと端末が暴走するのかどうなのか。
7.2.3 The form HTML はスルーで次に。
7.3 Signup failure
以下は失敗する試験なのかな。
$ bundle exec rspec spec/requests/user_pages_spec.rb \ > -e "signup with invalid information"
以下で試験 red ですね。良いのかな。
Failures: 1) User pages signup with invalid information should not create a user Failure/Error: expect { click_button submit }.not_to change(User, :count) AbstractController::ActionNotFound: The action 'create' could not be found for UsersController # (eval):2:in `click_button' # ./spec/requests/user_pages_spec.rb:30:in `block (5 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:30:in `block (4 levels) in <top (required)>'
ええと rake routes 確認してみると
$ rake routes users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy
/users で POST すると users#create が云々なのか。なので controller にアクション追加してるんですね。
def create @user = User.new(params[:user]) if @user.save # Handle a successful save. else render 'new' end end
アクション追加したらさきほどの試験がどうなるかというと green 終了しました。実行されてる試験は以下。
let(:submit) { "Create my account" } describe "with invalid information" do it "should not create a user" do expect { click_button submit }.not_to change(User, :count) end end
7.3.2 Signup error messages
エラーメセジ出漁用途として app/views/users/new.html.erb を以下な形に。
<div class="row"> <div class="span6 offset3"> <%= form_for(@user) do |f| %> <%= render 'shared/error_messages' %>
で、partial なソレも用意。
app/views/shared/_error_messages.html.erb
<% if @user.errors.any? %> <div id="error_explanation"> <div class="alert alert-error"> The form contains <%= pluralize(@user.errors.count, "error") %>. </div> <ul> <% @user.errors.full_messages.each do |msg| %> <li>* <%= msg %></li> <% end %> </ul> </div> <% end %>
M-x make-directory Enter Enter って知らなんだ (何
それは良いとしてこれで @user.errors.any? の時に上の partial が出力される形になっているはず。試験も green です。
$ bundle exec rspec spec/requests/user_pages_spec.rb \ > -e "signup with invalid information"
見栄え確認してみます。て、エラーメセジが出ねぇと思ったら new.html.erb を上書きしていませんでした。無事出力を確認。
7.4 Signup success
登録成功した時のソレを盛り込む、ということになるのか。
7.4.1 The finished signup form
とりあえず試験実行。
$ bundle exec rspec spec/requests/user_pages_spec.rb \ > -e "signup with valid information"
red 確認。
Failures: 1) User pages signup with valid information should create a user Failure/Error: expect { click_button submit }.to change(User, :count).by(1) ActionView::MissingTemplate: Missing template users/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/home/rms/OLDHome/rms/Documents/rails_proj/sample_app/app/views" # (eval):2:in `click_button' # ./spec/requests/user_pages_spec.rb:43:in `block (5 levels) in <top (required)>' # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in <top (required)>'
controller に処理を盛り込んでいませんので当り前。create アクションを以下にせよ、とのこと。
def create @user = User.new(params[:user]) if @user.save redirect_to @user else render 'new' end end
これで試験は all green になる模様。
$ bundle exec rspec spec/
all green 確認。すばらです。
7.4.2 The flash
flash というのも昔からある仕組みですね。app/views/layouts/application.html.erb 方面に以下を盛り込みなさいとのこと。
<body> <%= render 'layouts/header' %> <div class="container"> <% flash.each do |key, value| %> <div class="alert alert-<%= key %>"><%= value %></div> <% end %> <%= yield %> <%= render 'layouts/footer' %> <%= debug(params) if Rails.env.development? %> </div>
container なクラスの div な部分の中の flash.each なブロックか。で、登録成功時に情報出力と。
app/controllers/users_controller.rb
def create @user = User.new(params[:user]) if @user.save flash[:success] = "Welcome to the Sample App!" redirect_to @user else render 'new' end end
7.4.3 The first signup
ユーザ一件登録。Rails Tutorial/example@railstutorial.org で良いのかな。登録直後には flash が出力されて reload したら消える模様。確認 OK です。
7.4.4 Deploying to production with SSL
ここまでのソレで commit を作って master に merge してますね。
$ git add . $ git commit -m "Finish user signup" $ git checkout master $ git merge sign-up --no-ff
で、Heroku 方面でも云々してます。config/environments/production.rb な以下の部分を有効にするのかな。
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true
で、master ブランチに commit を作って
$ git commit -a -m "Add SSL in production"
Heroku 方面に push か。
$ git push heroku
deploy しているご様子。ちょっと時間かかってます。以下なコマンドも叩けとのこと。
$ heroku run rake db:migrate
で、heroku open とか heroku log とか出てますね。確かに signup にアクセスしたら https になってました。わははは。heroku logs も情報満載ですね。
別途余裕があれば exercise にも手を出してみようと思います。