いつもの
rails new passport -TB --skip-turbolinks
bundle
gemを追加しておく
gem "twitter-bootstrap-rails" gem "slim-rails" gem 'devise'
rails generate bootstrap:install static
忘れずに
deviseのセットアップ
rails g devise:install
すると以下が表示される
mPro:passport thr3a$ rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. If you are deploying on Heroku with Rails 3.2 only, you may want to set: config.assets.initialize_on_precompile = false On config/application.rb forcing your application to not access the DB or load models when precompiling your assets. 5. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================
コントローラーの作成
とりあえずサイト全体のindexを作成
rails g controller home index
モデルの作成
rails g devise User
ちなみに以下のマイグレーションが生成される
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| ## Database authenticatable 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 null: false end 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
モデルも以下
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable end
それぞれどんな機能持っているかの確認はここが詳しい。とりあえずデフォルトで
ビューの作成
app/views/home/index.html.slimを以下に変更
- if user_signed_in? p = current_user.email =link_to "Settings", edit_user_registration_path =link_to "Logout", destroy_user_session_path, method: :delete - else =link_to "Sign up", new_user_registration_path =link_to "Login", new_user_session_path
大元のerbもapp/views/layouts/application.html.slimに変更してメッセージを追加
doctype html html head title My App meta name="viewport" content="width=device-width, initial-scale=1.0" = stylesheet_link_tag "application", media: 'all' = javascript_include_tag "application" = csrf_meta_tags body - if notice p.alert.alert-success = notice - if alert p.alert.alert-danger = alert = yield
ルーティングの設定
config/route.rbを以下に変更 deviseはリダイレクトにroot_path
使ってるので指定しないと死ぬ
devise_for :users get 'home/index' root 'home#index'
以上でユーザー登録機能までの一通りが実装される。スゲェ簡単
試しに登録してみるとこんな感じでDBに入る
=> #<ActiveRecord::Relation [#<User id: 1, email: "a@a.com", encrypted_password: "$2a$10$DuA68xuU25/C8/cS5.7bVekwr/DV3N.4/DLutd3gndR...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 2, current_sign_in_at: "2015-11-06 05:46:14", last_sign_in_at: "2015-11-06 05:33:05", current_sign_in_ip: "::1", last_sign_in_ip: "::1", created_at: "2015-11-06 05:33:05", updated_at: "2015-11-06 05:46:40">]>
パスワードリセットのメールが送信できない
ふぇえ
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
ちゃんと説明読もうな
config/environments/development.rbに以下を例に設定してあげる。以下はActionmailerを利用したGmail経由の設定
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.delivery_method = :smtp #config.action_mailer.raise_delivery_errors = true config.action_mailer.smtp_settings = { :enable_starttls_auto => true, :address => 'smtp.gmail.com', :port => '587', :domain => 'smtp.gmail.com', :authentication => 'plain', :user_name => '<Gmailアカウント>@gmail.com', :password => '<Gmailパスワード>' }
ただしGoogleアカウント側にも設定が必要なので注意
日本語化
https://raw.githubusercontent.com/tigrish/devise-i18n/master/rails/locales/ja.ymlを適当にdevise.ja.ymlをconfig/localesにブチ込む
あとja.ymlに以下を追記
ja: activerecord: attributes: user: name: 名前 password: パスワード password_confirmation: パスワード確認 email: メールアドレス
無心で実行
rails g devise:views
deviseはerb以外のビューに対応していない。そこでerb2slim
を用いて変換する
erb2slim -d app/views/devise/
ちなみに以下のようなビューが生成されるらしい)
- app/views/devise/shared/_links.html.erb (リンク用パーシャル)
- app/views/devise/confirmations/new.html.erb (認証メールの再送信画面)
- app/views/devise/passwords/edit.html.erb (パスワード変更画面)
- app/views/devise/passwords/new.html.erb (パスワードを忘れた際、メールを送る画面)
- app/views/devise/registrations/edit.html.erb (ユーザー情報変更画面)
- app/views/devise/registrations/new.html.erb (ユーザー登録画面)
- app/views/devise/sessions/new.html.erb (ログイン画面)
- app/views/devise/unlocks/new.html.erb (ロック解除メール再送信画面)
- app/views/devise/mailer/confirmation_instructions.html.erb (メール用アカウント認証文)
- app/views/devise/mailer/reset_password_instructions.html.erb (メール用パスワードリセット文)
- app/views/devise/mailer/unlock_instructions.html.erb (メール用ロック解除文)
メールアドレスだけじゃなくて名前も登録したい
登録項目を増やすにはまず普通にマイグレーションを追加
rails g migration AddNameToUsers name
マイグレーションにてnameカラムオプションにnull: false, default: ""
を追加
class AddNameToUsers < ActiveRecord::Migration def change add_column :users, :name, :string, null: false, default: "" end end
必須項目にするならモデルにバリデーションを追加しておく
validates :name, presence: true, length: { maximum: 10 }
rake db:migrate:reset
したのちにビューに追加 以下は例
.field = f.label :name = f.text_field :name, autofocus: true
残念ながらこれだけでは終わらない。Railsたん最強罠であるStrong Parametersがnameパラメータを阻むからである。
そこで公式READMEを参考に以下を追加
class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) << :name devise_parameter_sanitizer.for(:sign_in) << :name devise_parameter_sanitizer.for(:account_update) << :name end end
indexページ等特定のページでは認証を必要としない
app/controllers/application_controller.rbにて
before_action :authenticate_user!, except: [:show, :index]
/users/sign_inを/users/loginに変更したい
ルーティングの変更はroutes.rbで行うことができる
デフォルトのルーティング
mPro:passport thr3a$ 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 home_index GET /home/index(.:format) home#index root GET / home#index
例えば
/users/sign_in
から/users/login
users/sign_out
から/users/logout
に変更したい場合は以下のようにする
devise_for :users, path_names: { sign_in: "login", sign_out: "logout"}
プロフィール画面欲しい
deviseは一発でそれっぽく生成してくれるがindexとshow(に相当するページ)は作らない。のでそこは自分でこしらえる。
コントローラー生成
rails g controller users index show
適当に作る
class UsersController < ApplicationController def index @users = User.all end def show @user = User.find(params[:id]) end end
ルーティングの設定 devise_for
の後に書かないと死ぬ
Rails.application.routes.draw do devise_for :users, path_names: { sign_in: "login", sign_out: "logout"} root 'home#index' →resources :users, :only => [:index, :show]
index.html.slim
ul - @users.each do |user| li = user.email
show.html.slim
h1 = @user.name p = @user.email
これでおk
編集後のリダイレクトを変えたい
編集後、デフォルトだとTOPページ(root_path
)に飛ぶけどそのまま編集ページに戻りたい場合だってあると思うの
どうもオーバーライドすることで実現できる。 app/controllers/users/registrations_controller.rbを新規作成して以下
class RegistrationsController < Devise::RegistrationsController protected def after_update_path_for(resource) edit_user_registration_path end end
あとはroutes.rbに以下を追記するだけ
devise_for :users, :controllers => { :registrations => "registrations" }
こことか多くのサイトがusers/registrations
してたんだけど何が違うんだろう(無理だった