学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース

Ruby on RailsでWebアプリケーション開発その31 管理ユーザ登録の実装

<<前  [TOP]  次>>


商品登録フォームをログインしたユーザしか使用できないように実装していきます。


まずはUserモデルを作成します。
作成するusersテーブルは以下のような構成になります。

  • name: ユーザ名(string型)
  • password_digest: ハッシュ化されたパスワードを格納(String型)


    コマンドプロンプトで「shop」フォルダに移動し、「rails generate scaffold User name:string password_digest:string」と入力します。
    f:id:MrRadiology:20180305163643p:plain
    途中scaffolds.scssファイルを上書きするか聞かれますが、今回は「n」を入力します。
    f:id:MrRadiology:20180305151636j:plain


    コマンドプロンプトで「rake db:migrate」と入力してマイグレーションを実行します。
    f:id:MrRadiology:20180305152539p:plain


    作成された「users」テーブルを確認してみます。
    f:id:MrRadiology:20180305163802p:plain


    「Gemfile」の最後に「gem 'bcrypt-ruby', '3.1.1.rc1', :require => 'bcrypt'」と追加します。


    【shop/Gemfile】

    source 'https://rubygems.org'
    
    
    # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
    gem 'rails', '4.2.10'
    # Use mysql as the database for Active Record
    gem 'mysql2', '>= 0.3.13', '< 0.5'
    # Use SCSS for stylesheets
    gem 'sass-rails', '~> 5.0'
    # Use Uglifier as compressor for JavaScript assets
    gem 'uglifier', '>= 1.3.0'
    # Use CoffeeScript for .coffee assets and views
    gem 'coffee-rails', '~> 4.1.0'
    # See https://github.com/rails/execjs#readme for more supported runtimes
    # gem 'therubyracer', platforms: :ruby
    
    # Use jquery as the JavaScript library
    gem 'jquery-rails'
    # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
    gem 'turbolinks'
    # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
    gem 'jbuilder', '~> 2.0'
    # bundle exec rake doc:rails generates the API under doc/api.
    gem 'sdoc', '~> 0.4.0', group: :doc
    
    # Use ActiveModel has_secure_password
    # gem 'bcrypt', '~> 3.1.7'
    
    # Use Unicorn as the app server
    # gem 'unicorn'
    
    # Use Capistrano for deployment
    # gem 'capistrano-rails', group: :development
    
    group :development, :test do
      # Call 'byebug' anywhere in the code to stop execution and get a debugger console
      gem 'byebug'
    end
    
    group :development do
      # Access an IRB console on exception pages or by using <%= console %> in views
      gem 'web-console', '~> 2.0'
    end
    
    # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
    gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
    
    gem 'coffee-script-source', '1.8.0'
    
    gem 'rails-i18n'
    
    gem 'will_paginate'
    
    gem 'kaminari'
    
    gem 'bcrypt-ruby', '3.1.1.rc1', :require => 'bcrypt'
    



    コマンドプロンプトで「bundle install」を実行します。
    f:id:MrRadiology:20180306110607p:plain
    f:id:MrRadiology:20180306110652j:plain


    検証メソッドの記述を行います。
    userモデルを以下のように編集します。


    【app/models/user.rb】

    class User < ActiveRecord::Base
    
    	validates :name, presence: true, uniqueness: true
    	has_secure_password
    
    end
    

    「presence: true」でnameフィールドが空でないこと、「uniquenss: true」で名前が重複していないことを検証しています。
    「has_secure_password」は再入力したパスワードが間違いないかどうかを検証するものです。
    この機能を利用するために「bcrypt-ruby」をgemでインストールしました。


    ユーザを作成した後、indexビューにリダイレクトし、ユーザ名をフラッシュ表示させるようにusersコントローラを編集します。
    編集するメソッドは「index()」「create()」「update()」の3つです。


    【app/controllers/users_controller.rb】

    class UsersController < ApplicationController
      before_action :set_user, only: [:show, :edit, :update, :destroy]
    
      # GET /users
      # GET /users.json
      def index
    	@users = User.order(:name)
    
    	respond_to do |format|
    	        format.html
    		format.json { render ison: @users }
    	end
      end
    
      # GET /users/1
      # GET /users/1.json
      def show
      end
    
      # GET /users/new
      def new
        @user = User.new
      end
    
      # GET /users/1/edit
      def edit
      end
    
      # POST /users
      # POST /users.json
      def create
        @user = User.new(user_params)
    
        respond_to do |format|
          if @user.save
            format.html { redirect_to users_url, notice: "ユーザ名「#{@user.name}」を作成しました。" }
            format.json { render json: @user, status: :created, location: @user }
          else
            format.html { render :new }
            format.json { render json: @user.errors, status: :unprocessable_entity }
          end
        end
      end
    
      # PATCH/PUT /users/1
      # PATCH/PUT /users/1.json
      def update
    
    	@user = User.find(params[:id])
    
    	respond_to do |format|
    		if @user.update(user_params)
    			format.html { redirect_to users_url, notice: "ユーザ「#{@user.name}」を更新しました。" }
    			format.json { head :ok }
    		else
    			format.html { render :edit }
    			format.json { render json: @user.errors, status: :unprocessable_entity }
    		end
    	end
      end
    
      # DELETE /users/1
      # DELETE /users/1.json
      def destroy
        @user.destroy
        respond_to do |format|
          format.html { redirect_to users_url, notice: "ユーザ「#{@user.name}」を削除しました。" }
          format.json { head :no_content }
        end
      end
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_user
          @user = User.find(params[:id])
        end
    
        # Never trust parameters from the scary internet, only allow the white list through.
        def user_params
          params.require(:user).permit(:name, :password, :password_digest)
        end
    end
    

    最後に記述してある「user_params」メソッドも一部変更しています。
    permit()に「:password」パラメータも渡すようにしています。
    これをしないと検証で「:password」が入力されていませんとエラーが出ます。

    def user_params
          params.require(:user).permit(:name, :password, :password_digest)
    end
    



    次に「index」ビューの編集をします。


    【app/views/users/index.html.erb】

    <% if notice %>
    <p id="notice"><%= notice %></p>
    <% end %>
    <br>
    <h1>管理ユーザ</h1>
    <br>
    <table>
      <thead>
        <tr>
          <th>ユーザ名</th>
          <th colspan="3"></th>
        </tr>
      </thead>
    
      <tbody>
        <% @users.each do |user| %>
          <tr>
            <td><%= user.name %></td>
            <td><%= link_to '詳細', user, :class => 'btn' %></td>
            <td><%= link_to '編集', edit_user_path(user), :class => 'btn' %></td>
            <td><%= link_to '削除', user, method: :delete, data: { confirm: '本当に削除してよろしいですか?' }, :class => 'btn' %></td>
          </tr>
        <% end %>
      </tbody>
    </table>
    
    <br>
    
    <%= link_to '新しいユーザ作成', new_user_path, :class => 'btn' %>
    



    パスワードのフィールドは削除しました。
    まだユーザがいないので何も表示されていません。
    アクセスするアドレスは「http://localhost:3000/users」になります。
    f:id:MrRadiology:20180306100224p:plain


    新規ユーザ作成とユーザ情報更新のフォームビューを編集します。


    【app/views/users/_form.html.erb】

    <%= form_for(@user) do |f| %>
      <% if @user.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
    
          <ul>
          <% @user.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    <br>
    <div class="order_form">
      <fieldset>
        <legend>ユーザ情報の入力</legend>
        <br>
        <div class="field">
         <%= f.label :名前 %>
         <%= f.text_field :name, size: 40 %>
        </div>
        <br>
        <div class="field">
         <%= f.label :パスワード入力 %>
         <%= f.password_field :password, size: 40 %>
        </div>
        <div class="field">
         <%= f.label :パスワード確認 %>
         <%= f.password_field :password_confirmation, size: 40 %>
        </div>
        <br>
        <div class="actions">
         <%= f.submit %>
        </div>
       </fieldset>
    </div>
    <% end %>
    



    あわせて「new」ビューも編集します。


    【app/views/users/new.html.erb】

    <h1>新規ユーザ登録</h1>
    <br>
    <%= render 'form' %>
    <br>
    <%= link_to 'ユーザ一覧に戻る', users_path, :class => 'btn' %>
    



    f:id:MrRadiology:20180306104227p:plain


    ではユーザを登録してみます。
    f:id:MrRadiology:20180306104343j:plain


    f:id:MrRadiology:20180306111022p:plain


    usersテーブルを確認してみましょう。
    f:id:MrRadiology:20180306111851p:plain
    「name」にユーザ名、「password_digest」にハッシュ化されたパスワードが格納されているのがわかります。


    <<前  [TOP]  次>>