##この章では何するの?
ユーザー登録機能を追加するよ
HTML フォームを使ってWebアプリケーションに登録情報を送信
ユーザーを新規作成して情報をデータベースに保存
作成されたユーザーの新しいプロフィールを表示できるようにするために、ユーザーを表示するためのページを作成
ユーザー用のRESTアーキテクチャを実装する第一歩を踏み出すよ
##サイトにdebug情報の追加
ビルトインの debug
メソッドとparams
変数を使い、デバッグ用の情報が表示されるようになる。
<%= debug(params) if Rails.env.development? %>
開発環境だけでdebug情報を出力したいときは下記コード追加。
if Rails.env.development?
logサンプル
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
controller: static_pages
action: home
permitted: false
##Usersリソース
RESTの原則に従う場合、リソースへの参照はリソース名とユニークなIDを使うのが普通
ユーザーをリソースとみなす場合、id=1のユーザーを参照するということは、/users/1というURLに対してGETリクエストを発行するということを意味する。
users/1 のurlを有効にするために下記追加
resources :users
ユーザーのURLを生成するための多数の名前付きルート(5.3.3)と共に、RESTfulなUsersリソースで必要となるすべてのアクションが利用できるようになる
プロフィール表示用のviewファイルの作成
<%= @user.name %>, <%= @user.email %>
Usersコントローラに show
アクション追加
class UsersController < ApplicationController
#追加
def show
@user = User.find(params[:id])
end
def new
end
end
##debuggerメソッド
コントローラーにdebugger
を追加すると、railsのコンソール上でデバッグできる
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
debugger #これ追加
end
def new
end
end
ctrl + d
で抜けれる
##formの実装
form_with
ヘルパーメソッドを使用する
##エラーメッセージについて
railsは無効な内容の送信によって元のページに戻されると、CSSクラスfield_with_errors
を持ったdivタグでエラー箇所を自動的に囲んでくれる機能がある。
##form用のテスト
#コントローラーの作成
$rails generate integration_test users_signup
ユーザー登録ボタンを押したときに(ユーザー情報が無効であるために)ユーザーが作成されないことを確認する。
getメソッドを使ってユーザー登録ページにアクセス
get signup_path
フォーム送信をテストするためには、 users_pathに対してPOSTリクエストを送信する
##flash
登録完了後に表示されるページにメッセージを表示し(この場合は新規ユーザーへのウェルカムメッセージ)、2度目以降にはそのページにメッセージを表示しないようにする。
上記のような情報を表示するためにrailsでは、flashという特殊な変数を使う。
flash変数に代入したメッセージは、リダイレクトした直後のページで表示できるようになる。
##ユーザーが作成されたことを確認するテスト
assert_difference
メソッドを使いテストする
assert_no_difference
と同様に、このメソッドは第一引数に文字列('User.count')を取り、assert_difference
ブロック内の処理を実行する直前と、実行した直後のUser.countの値を比較する。
ここでrails t
したら下記のエラーが出た
ERROR["test_invalid_signup_information", #<Minitest::Reporters::Suite:0x000055eba2f5b2c8 @name="UsersSignupTest">, 1.2418686970013368]
test_invalid_signup_information#UsersSignupTest (1.24s)
Nokogiri::CSS::SyntaxError:
Nokogiri::CSS::SyntaxError: unexpected '#' after '[#<Nokogiri::CSS::Node:0x000055eba2f4a4f0 @type=:ELEMENT_NAME, @value=["div"]>]'
test/integration/users_signup_test.rb:14:in `block in <class:UsersSignupTest>'
Finished in 1.31543s
15 tests, 30 assertions, 0 failures, 1 errors, 0 skips
エラーを吐いているコードはどうやら下記で、CSS::SyntaxError
と出ているのでcss周りのエラーの模様。
assert_select 'div#<CSS id for error explanation>'
assert_select 'div.<CSS class for field with error>'
assert_select
は、特定のHTMLタグが存在するかどうかをテストするメソッドだった。
そのため、下記のように修正。無事テストがとおる。
#error explanationのid名を指定
assert_select 'div#error_explanation'
#field with errorのときのクラス名を指定
assert_select 'div.field_with_errors'
##本番環境でのSSL
この章で制作したユーザー登録フォームで送信すると、名前やメールアドレス、パスワードといったデータがネットワーク越しに流されていく。
これを修正するために、Transport Layer Security(TLS)を使う。
TLS: ローカルのサーバーからネットワークに流れる前に、大事な情報を暗号化する技術
方法
production.rb
に一行修正を加える
具体的には、config
に「本番環境ではSSLを使うようにする」という設定をする
config.force_ssl = true #一行追加
次に、遠隔にあるサーバーのSSLをセットアップする。
本番用のWebサイトでSSLを使えるようにするためには、ドメイン毎にSSL証明書を購入し、セットアップする必要がある。
証明書周りは工数かかるが、HerokuのSSL証明書に便乗する方法でその作業をせずに済む。
独自ドメインの場合は証明書周りの作業必要。
##本番環境用のサーバー
WEBrickをPumaに置き換える。
理由は、WEBrickは簡単にセットアップできたり動せることが特長だが、著しいトラフィックを扱うことには適していないため。
Pumaは多数のリクエストを捌くことに適したRuby/Rackアプリケーション用のサーバーである。
Pumaのファイルを書き換え
# Pumaの設定ファイル
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { ENV['RACK_ENV'] || "production" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restart
./Procfile
を制作
web: bundle exec puma -C config/puma.rb
DBを本番向けに設定
#下記追加
production:
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://railsguides.jp/configuring.html#データベース接続をプールする
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
database: sample_app_production
username: sample_app
password: <%= ENV['SAMPLE_APP_DATABASE_PASSWORD'] %>