Railsアプリにdeviseでユーザー認証を

先日から作り始めた Web アプリに、ユーザー認証を付けたい。ググってみると、devise っていうのがいいみたいなので、それを使うことにした。参考にしたのは以下のページ。

 cf. Railsでログイン、ユーザー登録機能を簡単に実装できる devise がスゴすぎると話題 – lough-raku^^
 cf. Rails4 にて Devise でユーザー登録・ログイン認証・認可の機能を追加 – EasyRamble
 cf. DeviseでSign up時にメール確認する – 悪あがきプログラマー

まずはインストール

Gemfile に以下の行を追加。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
gem 'devise'
gem 'devise'
gem 'devise'

そいでもってインストール。

takatoh@nightschool:~/w/lathercraft$ bundle install

ジェネレータでモデルを作成

takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise:install
takatoh@nightschool:~/w/lathercraft$ bundle exec rails generate devise User

モデル名は User にした。この時点で次のようなマイグレーションファイルができる。今回はユーザー名を入れたかったので name フィールドを追加、加えて Email での確認をしたかったので、confirmable のところがコメントアウトしてあったのを外した。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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, :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 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, :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 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, :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

これで rake db:migration、サーバを起動して localhost:3000/users/sign_up にアクセスすると、下の画面のようにサインアップできるようになる。

user-sign-up

Sign up ボタンをクリックすれば OK だ。といってもまだメールを送る設定とかしていないので、サインアップは完了できない。でも、ログには出てくるはず……って、あれぇ?エラーになった。

devise-registration-error

なんでだ?
参考にしたページによれば、ログにメールが出力されて confirm 用のページへのリンクが乗っているはずなんだけど。うーん、勝手に name カラムを追加したのが悪いんだろうか。

いろいろ調べて試した結果

↓このページで答えを見つけた。

 cf. Ruby on Rails + Deviseの組み合わせでMissing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true – もっとクールにプログラミング

それと他にも間違いと思しきところが。結局直したのは次の3ヶ所。

1つ目は、マイグレーションファイルの下の方で次の行がコメントアウトされていたのを有効にした。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
add_index :users, :confirmation_token, unique: true
add_index :users, :confirmation_token, unique: true
add_index :users, :confirmation_token, unique: true

2つ目は、app/models/user.rb に :confirmable オプションを追加した。

最後、3つ目が上のページにも書いてあるように、config/environments/development.rb の最後に一行追加。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
config.action_mailer.default_url_options = { :host =&gt; 'localhost:3000' }
config.action_mailer.default_url_options = { :host =&gt; 'localhost:3000' }
config.action_mailer.default_url_options = { :host =&gt; 'localhost:3000' }

これでやっと、メールがログに出るようになった。

confirmation

href=”…” に示されているアドレスにアクセスすると、無事サインインの画面が出てサインインできた。

めでたしめでたし。というところで、今日はここまで。