LoginSignup
80
78

More than 5 years have passed since last update.

Deviseのカスタマイズ。OAuthのときはemail入力を不必要にして、""でも可にする

Last updated at Posted at 2013-05-14

Railscasts#235で作成したDevise入りアプリケーション。

これをカスタマイズして、

  • OmniAuthでユーザー登録した場合はemailの入力は不要にする
  • OmniAuthで登録したユーザーが自分のユーザー情報を編集したとき、emailフォームを空白にしても、uniqueバリデーションでアップデートを拒否されないようにする

以上の2つを満たすようにしたい。

なお現在Deviseのアップデートに伴い、より簡単になったOAuth対応機能を使ったRailscasts#235revisedが公開されている。が、アプリケーション作成の際に旧バージョンのRailscastsを参考にしたので、今さら変えられない。

  1. インデックスを消す
  2. email_required?をオーバーライド
  3. emailカラムのデフォルト変更

の順番で作業を行う。

インデックスを消す

Deviseで

$ rails g devise user

したときにできる20130101111111_devise_create_users.rbには、

db/migrate/20130101111111_devise_create_users.rb
add_index :users, :email, :unique => true

というインデックス追加を含んでいる。
このインデックスを残したままだとまずいので、まずこれを消す。

$ rails g migration remove_index_email_from_users

でできた20130514071534_remove_index_email_from_users.rbを

db/migrate/20130514071534_remove_index_email_from_users.rb
class RemoveIndexEmailFromUsers < ActiveRecord::Migration
  def up
    remove_index :users, :email
  end

  def down
    add_index :users, :email, unique: true
  end
end

と書きかえる。

$ rake db:migrate

でマイグレーション適用。インデックス削除ができたことはdb/schema.rbで確認できる。

email_required?をオーバーライド

email_required?をオーバーライドすれば、devise内のemailのバリデーション設定をカスタマイズできる。
email_required? メソッドは、deviseの/lib/devise/models/validatable.rbにある、

lib/devise/models/validatable.rb
validates_presence_of   :email, :if => :email_required?

で、emailのvalidates_presence_ofを行うかの判定に使われている。
そのコードはこちら。
https://github.com/plataformatec/devise/blob/c179cef365f7188c91cbbc3db924a9f1f9563c3c/lib/devise/models/validatable.rb#L29

なので、email_required?の返り値をfalseにすると、emailのvalidates_presence_ofバリデーションを行わない。

具体的にどうすればよいかというと、

app/models/user.rb
  def email_required?
    (authentications.empty? || !email.blank?) && super
  end

とuserモデルに書く。これで、email_required? メソッドをオーバーライドできる。条件文が複雑なので、整理すると、

Emailの存在が必要な場合

  • ユーザーがOAuthのauthenticationsを持っていないとき
  • 空白ではないEmailを入力したとき

Emailの存在が不要な場合

  • ユーザーがOAuthのauthenticationsを持っている
  • かつ、Emailが空白かそもそもnilのとき

となる。

emailカラムのデフォルト変更

DBスキーマのemailカラムは

db/shema.rb
t.string   "email",     :default => "", :null => false

となっている。デフォルトで空白、nullは許可しない状態。
デフォルトでnullにして、nullを許可したい。

$ rails g migration change_email_default

でmigrationファイルを作って、

db/migrate/20130514065947_change_email_default.rb
class ChangeEmailDefault < ActiveRecord::Migration
  def up
    change_column :users, :email, :string, null: true
    change_column_default :users, :email, nil
  end

  def down
    change_column :users, :email, :string, null: false
    change_column_default :users, :email, ""
  end
end

と書きかえる。で、

$ rake db:migrate

すれば、

db/shema.rb
    t.string   "email"

と、nilを許可して、デフォルトをnilにできた。

あとは、サーバを再起動すれば、OAuthで登録したユーザーに関してはemail入力が不要になる。もうuniqueバリデーションで弾かれることはない。

80
78
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
78