Rails と devise の話はまだ続くよ。今日は devise のビューとコントローラをカスタマイズする。
やっぱりユーザー名がほしい
ユーザーアカウントに Email だけじゃなくて、やっぱりユーザー名がほしい。というわけで、migration スクリプトに2行追加。
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :name, null: false, default: ""
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false
# Only if lock strategy is :failed_attempts
# t.string :unlock_token
# Only if unlock strategy is :email or :both
# t.datetime :locked_at t.timestamps
end
add_index :users, :name, unique: true
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
そしてデータベースの作り直し。
takatoh@nightschool:~/w/lathercraft$ bundle exec rake db:drop
takatoh@nightschool:~/w/lathercraft$ bundle exec rake db:migrate
devise のビューをコピーしてカスタマイズ
デフォルトでは gem のビューが使われているけど、カスタマイズするためにビューをコピーする。
takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise:views users
invoke Devise::Generators::SharedViewsGenerator
create app/views/users/shared
create app/views/users/shared/_links.erb
invoke form_for
create app/views/users/confirmations
create app/views/users/confirmations/new.html.erb
create app/views/users/passwords
create app/views/users/passwords/edit.html.erb
create app/views/users/passwords/new.html.erb
create app/views/users/registrations
create app/views/users/registrations/edit.html.erb
create app/views/users/registrations/new.html.erb
create app/views/users/sessions
create app/views/users/sessions/new.html.erb
create app/views/users/unlocks
create app/views/users/unlocks/new.html.erb
invoke erb
create app/views/users/mailer
create app/views/users/mailer/confirmation_instructions.html.erb
create app/views/users/mailer/reset_password_instructions.html.erb
create app/views/users/mailer/unlock_instructions.html.erb
とりあえず、sign up するときの app/views/users/registrations.new.html.erb と sign in するときの app/views/users/sessions/new.html.erb にユーザー名の欄を付け加えた。
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div>
<%= f.label :name %>
<%= f.email_field :name, autofocus: true %>
</div>
<div>
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<div>
<%= f.label :password %>
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div>
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "users/shared/links" %>
<h2>Sign in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div>
<%= f.label :name %>
<%= f.email_field :name, autofocus: true %>
</div>
<div>
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<div>
<%= f.label :password %>
<%= f.password_field :password, autocomplete: "off" %>
</div>
<% if devise_mapping.rememberable? -%>
<div>
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end -%>
<div>
<%= f.submit "Sign in" %>
</div>
<% end %>
<%= render "users/shared/links" %>
コントローラーのカスタマイズ
コントローラーをカスタマイズするには、Devise::SessionsController, Devise::RegistrationsController, Devise::PasswordsController を継承したクラスを作成して、各メソッドをオーバーライドすればいいようだ。どのメソッドをオーバーライドすればいいかを、bundle exec rake routes
で確認する。
takatoh@nightschool:~/w/lathercraft$ bundle exec rake routes
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
user_confirmation POST /users/confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
GET /users/confirmation(.:format) devise/confirmations#show
(後略)
これを見ると、とりあえずは registration#new と sessions#new かな。それぞれこうした。
class Users::RegistrationsController < Devise::RegistrationsController
end
Devise::SessionsController
def new
super
end
def create
super
end
def destroy
super
end
end
ついでに PasswordsController も。
class Users::PasswordsController < Devise::PasswordsController
end
ルーティングの設定
作ったコントローラーを使うように、ルーティングを変更する。
Rails.application.routes.draw do
devise_for :users, :controllers => {
:registrations => "users/registrations",
:sessions => "users/sessions",
:passwords => "users/passwords"
}
(後略)
ルーティングを確認してみよう。
takatoh@nightschool:~/w/lathercraft$ bundle exec rake routes
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) users/sessions#new
user_session POST /users/sign_in(.:format) users/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) users/sessions#destroy
user_password POST /users/password(.:format) users/passwords#create
new_user_password GET /users/password/new(.:format) users/passwords#new
edit_user_password GET /users/password/edit(.:format) users/passwords#edit
PATCH /users/password(.:format) users/passwords#update
PUT /users/password(.:format) users/passwords#update
cancel_user_registration GET /users/cancel(.:format) users/registrations#cancel
user_registration POST /users(.:format) users/registrations#create
new_user_registration GET /users/sign_up(.:format) users/registrations#new
edit_user_registration GET /users/edit(.:format) users/registrations#edit
PATCH /users(.:format) users/registrations#update
PUT /users(.:format) users/registrations#update
DELETE /users(.:format) users/registrations#destroy
user_confirmation POST /users/confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
GET /users/confirmation(.:format) devise/confirmations#show
(後略)
confirmation のルーティングが devise のままだけど大丈夫かな。
試しにサインアップしてみると、無事うまく行った。