今回はユーザー登録ページを作りました。
Railsには良い機能があってデバッグ画面を開発画面に表示できるからとても楽。
今回ユーザー登録するためにルーティングに新たに追加した
resources :users
これを追加するだけでusersの様々なURLや名前付きルートが使えるようになる。
HTTPリクエスト URL アクション 名前付きルート 用途
GET /users index users_path すべてのユーザーを一覧するページ
GET /users/1 show user_path(user) 特定のユーザーを表示するページ
GET /users/new new new_user_path ユーザーを新規作成するページ(ユーザー登録)
POST /users create users_path ユーザーを作成するアクション
GET /users/1/edit edit edit_user_path(user) id=1のユーザーを編集するページ
PATCH /users/1 update user_path(user) ユーザーを更新するアクション
DELETE /users/1 destroy user_path(user) ユーザーを削除するアクション
ただまだルーティングだけなのでコントローラーにも随時追加していくことになる。
ユーザーページを表示するには
users/1みたいにidのページを表示したいのでそのときはparams[:id]で取得することができる
なのでそのidのなめなどを表示するためにコントローラーに記述する
def show
@user = User.find(params[:id])
end
これでidの情報を取ってくることができる。
また画像表示にはGravatarを使う。
Gravatarは無料のサービスで、プロフィール写真をアップロードして、指定したメールアドレスと関連付けることができる。
userヘルパーにメソッドを作って表示させることにする。
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
また
def gravatar_for(user, size: 80)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
みたいに大きさを指定したりできる。
ユーザー表示できるようになったので
次は登録ページを作った。
まずは登録ページでUserオブジェクトにデータ送信したりするために
def new
@user = User.new
end
を記入することにする
そしてフォームを作る
<%form_with(model: @user, local: true) do |f| %>
end
fオブジェクトは、HTMLフォーム要素(テキストフィールド、ラジオボタン、パスワードフィールドなど)に対応するメソッドが呼び出されると、@userの属性を設定するために特別に設計されたHTMLを返します
<%= f.label :name %>
<%= f.text_field :name %>
は
<label for="user_name">Name
<input id="user_name" name="user[name]" type="text" />
のように生成される
あとはフォーム送信で失敗したときにエラーメッセージを表示させるために
まずはcreateコントローラーを作って成功のときと失敗の時を分ける
def create
@user = User.new(params[:user]) # 実装は終わっていないことに注意!
if @user.save
# 保存の成功をここで扱う。
else
render 'new'
end
end
上のparams[:user]だとparamsハッシュ全体を初期化するという行為はセキュリティ上、極めて危険。
仮に管理者権限のカラムがあってそれを誰でも送信できるようになるとすると誰でも管理者権限が持てるということになってしまってとても危険なのでこの場合、paramsハッシュでは:user属性を必須とし、名前、メールアドレス、パスワード、パスワードの確認の属性をそれぞれ許可し、それ以外を許可しないようにしたいと考えてるなのでコントローラーに
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
そして先程のところを
@user = User.new(user_params)
直すと良い
あとはエラーメッセージをフォームに差し込む
ついでに失敗したときのテストも書いとく
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
end
これはassert_no_differenceメソッドのブロック内でpostを使い、メソッドの引数には'User.count'を与えています。これはassert_no_differenceのブロックを実行する前後で引数の値(User.count)が変わらないことをテストしている。
あとはちゃんと登録できたときの処理を書く。
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render 'new'
end
end
また成功したときにフラッシュを表示したほうがわかりやすいので
flash[:success] = "Welcome to the Sample App!"をコントローラーに追加する
あとはビューページに追加する
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
そして次は成功したときのテストを書く
test "valid signup information" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: { user: { name: "Example User",
email: "user@example.com",
password: "password",
password_confirmation: "password" } }
end
follow_redirect!
assert_template 'users/show'
end
さっきとは逆でassert_differenceブロック内の処理を実行する直前と、実行した直後のUser.countの値を比較します。第二引数はオプションですが、ここには比較した結果の差異(今回の場合は1)を渡しますfollow_redirect!は、POSTリクエストを送信した結果を見て、指定されたリダイレクト先に移動するメソッドです。
またflashのビューへの記述は
<%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
ともかける
あとはSSLの設定やサーバーの設定などをやったこれはたぶんそれぞれ違うだろうからいずれやることになると思う
今後はログイン機能などを作っていくことになる