読者です 読者をやめる 読者になる 読者になる

Rodhos Soft

備忘録を兼ねた技術的なメモです。

チュートリアルをやってみる。ユーザ登録画面編

これは以下のチュートリアルをやってみた際のログである。

第7章 ユーザー登録 | Rails チュートリアル

ユーザ表示ページに表示するもの

  1. ユーザのプロファイル写真
  2. ユーザデータ
  3. マイクロポスト一覧

デバッグ表示

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
...
  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
  </body>
</html>

Rails.env.development?がtrueならdebug(params)が表示される。
つまり開発環境でしか表示されない。

app/assets/stylesheets/custom.css.scss

@mixin box_sizing {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}


/* miscellaneous */

.debug_dump {
  clear: both;
  float: left;
  width: 100%;
  margin-top: 45px;
  @include box_sizing;
}

ルーティング

config/routes.rb

SampleApp::Application.routes.draw do
    resources :users
    root  'static_pages#home'
    match '/signup',  to: 'users#new',            via: 'get'
    match '/help',    to: 'static_pages#help',    via: 'get'
    match '/about',   to: 'static_pages#about',   via: 'get'
    match '/contact', to: 'static_pages#contact', via: 'get'
....

resources :usersとすることで以下のRESTfulなアクションが利用できるようになる。

リクエスト URL アクション 名前付きルート
GET /users index user_path
GET /users/1 show user_path(1)
GET /users/new new new_user_path
POST /users create users_path
GET /users/1/edit edut edit_user_path(user)
PATCH /users/1 update user_path(user)
DELETE /user/1 destroy user_path(user)

ユーザ用のビューをつくる。

app/views/users/show.html.erb

<%= @user.name %>, <%= @user.email %>

コントローラ
app/controllers/users_controller.rb

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
    end
    
    def new
    end
end

プロフィール写真をつける

Gtavatar
gravatar_for関数はusers_helperで定義。
app/views/users/show.html.erb

<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>

app/helpers/users_helper.rb

    # 与えられたユーザーのGravatar (http://gravatar.com/) を返す。
    def gravatar_for(user)
        gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
        gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
        image_tag(gravatar_url, alt: user.name, class: "gravatar")
    end
確認
user = User.create(name:"p",email:"op@poi.mail",password:"poipoi", password_confirmation:"poipoi")
user.save
rails server

サイドバー作成

app/views/users/show.html.erb

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="span4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
  </aside>
</div>


app/assets/stylesheets/custom.css.scss

/* sidebar */

aside {
  section {
    padding: 10px 0;
    border-top: 1px solid $grayLighter;
    &:first-child {
      border: 0;
      padding-top: 0;
    }
    span {
      display: block;
      margin-bottom: 3px;
      line-height: 1;
    }
    h1 {
      font-size: 1.4em;
      text-align: left;
      letter-spacing: -1px;
      margin-bottom: 3px;
      margin-top: 0px;
    }
  }
}

.gravatar {
  float: left;
  margin-right: 10px;
}

ユーザ登録フォーム

タイトルがあり、

  1. name
  2. email
  3. password
  4. condirmation

の入力項目があり、
その下にcreateボタンがある。

ユーザデータのリセット

一度リセットしておく

bundle exec rake db:reset
bundle exec rake db:test:prepare

User.countが0であることをrailsコンソールで確認。

フォームのセット 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>

form_forはフォームを作る。ここから<%end>までがform_forであり、
f.label,f.textなどを使って設定していく。

app/controllers/users_controller.rb

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
    end
    
    def new
        @user = User.new
    end
end

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;
}

ローカルサーバで確認

rails server
エラー表示用のモックアップ

前述のフォームの登録は

<form action="/users" class="new_user" id="new_user" method="post">

となっておいるので"/users"にPOSTリクエストが送られるが、これは前述の表のように、
createアクションと結びつけられている。
よって、このcreateアクションでユーザの登録と、その失敗を記述する。

app/controllers/users_controller.rb

class UsersController < ApplicationController
 ....    
    def create
        @user = User.new(params[:user])    # 実装は終わっていないことに注意!
        if @user.save
            # 保存の成功をここで扱う。
            else
            render 'new'
        end
    end
end


これだとparams[:user]の中身を変更されて渡される危険性があるため、以下の方法に従う。

class UsersController < ApplicationController

......
    
    def create
        @user = User.new(user_params)
        if @user.save
            # 保存の成功をここで扱う。
            else
            render 'new'
        end
    end
    
    private
    
    def user_params
        params.require(:user).permit(:name, :email, :password,
                                     :password_confirmation)
    end
end

params.require(:user)はユーザ属性を必須とし、permitで許可する属性をしていている。

エラー表示用のタグを埋め込む
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| %>
    <%= render 'shared/error_messages' %>
....
    <% end %>
  </div>
</div>


renderを使って、パーシャル埋め込みをしている。よって、中身は_error_messages.html.erbに書く。
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 %>

pluralizeはテキストヘルパー
pluralize(1, "error") <==> "1 error"
pluralize(2, "error") <==> "2 errors"

cssも調整
app/assets/stylesheets/custom.css.scss

#error_explanation {
  color: #f00;
  ul {
    list-style: none;
    margin: 0 0 18px 0;
  }
}

.field_with_errors {
  @extend .control-group;
  @extend .error;
}

@extendはSassの関数、Bootstrapの.control-groupと.errorを使用している。
.field_with_errorsは、railsがエラーが出たフォーム欄に与えるクラス。

ここまででローカルサーバで確認

rails server

データベース保存

  1. 登録するとリダイレクトしてユーザのページへいく。

app/controllers/users_controller.rb

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
    end
    
    def new
        @user = User.new
    end
    
    def create
        @user = User.new(user_params)
        if @user.save
            redirect_to @user
            else
            render 'new'
        end
    end
    
    private
    
    def user_params
        params.require(:user).permit(:name, :email, :password,
                                     :password_confirmation)
    end
end

redirect_to @userの一文でUser表示ページへいく。

ウェルカムメッセージを入れる。
app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
...
  <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>
....
  </body>
</html>

<% flash.each do |key, value| %>

<%= value %>
<% end %>

が入っている。flash[:success] = "Welcome to the Sample App!"が入っていれば、
これは

<div class="alert alert-success">Welcome to the Sample App!</div>

と表示される。

その代入をcontroller側に入れる。
app/controllers/users_controller.rb

class UsersController < ApplicationController
.....    
    def create
        @user = User.new(user_params)
        if @user.save
            flash[:success] = "Welcome to the Sample App!"
            redirect_to @user
            else
            render 'new'
        end
    end
    
    private
    
    def user_params
        params.require(:user).permit(:name, :email, :password,
                                     :password_confirmation)
    end
end

ここでローカルサーバで確認してみる。

rails server

本番環境にSSL導入

config/environments/production.rb

SampleApp::Application.configure do
....
 # Force all access to the app over SSL, use Strict-Transport-Security,
  # and use secure cookies.
  config.force_ssl = true
end

herokuにもpush
本番データベースでマイグレーション

heroku run rake db:migrate
heroku open