問題
deviseとomniauth-twitterを使ってTwitterログインできるようにしようと
各種設定を行ったが、新規登録をするとエラーが発生してしまう。
自分はmodels/user.rb
にはこのような記述をした
def self.from_omniauth(auth)
find_or_create_by(provider: auth[:provider], uid: auth[:uid]) do |user|
user.uid = auth[:uid],
user.provider = auth[:provider],
user.username = auth[:username]
end
end
その結果、新規登録ボタンを押しても
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."provider" = ? AND "users"."uid" = ? LIMIT ? [["provider", "twitter"], ["uid", "伏せますね"], ["LIMIT", 1]]
↳ app/models/user.rb:9
(0.0ms) begin transaction
↳ app/models/user.rb:9
(0.0ms) rollback transaction
とロールバックしてしまい登録できない。
原因
原因はすぐにわかった。
Userモデルには、Twitter登録用にuid, provider, username
という3つの
カラムを登録したが、それとは別に通常ログイン用の email
や password
カラムもある。
( rails g devise:model User
時に自動設定されるはず)
てことはemail
や password
にはvalidationが設定されているため、
uid, provider, username
と一緒にemail, password
にもvalidationを
満たすような値を設定しなければならない。
解決策
email, passwordにダミーの値を入れて解決した。
# def self.from_omniauth(auth)
# find_or_create_by(provider: auth[:provider], uid: auth[:uid]) do |user|
# user.uid = auth[:uid],
# user.provider = auth[:provider],
# user.username = auth[:username],
user.email = self.dummy_email(auth), #emailにダミーを設定する
user.password = Devise.friendly_token[0, 10] #passwordに適当な値を設定する
# end
# end
private
def self.dummy_email(auth)
"#{auth[:username]}_#{auth[:uid]}@example.com"
end
ちなみに
user
が一人も登録されていないとする。
user.rb
にuid, provider, username
だけ設定してTwitterでログインしようとすると、
登録失敗後、uid, provider, username
がキャッシュされる場合がある。
その場合、その後に(通常の)新規登録画面で、email
やpassword
を入力して新規登録すると、
フォームで設定された値によってはuid, providerm username
がキャッシュされたまま
id=1のユーザとして登録されてしまうので、注意が必要。
つまり、uid, provider, username
で登録(失敗)して、
それとは別にemail, password
で登録したはずなのに
uid, provider, username, email, password
をもつuserが作られてしまうということ。
登録後にコンソールでUser.all
打って確認する必要がありそう。。
おわり