質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

2183閲覧

[Railsチュートリアル 11章]アカウントの有効化ができない

gussan-me

総合スコア7

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/02/11 03:20

編集2021/02/12 12:31

Railsチュートリアル勉強中の者です。

「sign upをした後、送られてきたメール内のリンクをクリックすることでアカウントを有効化する」
という機能を作成しておりますが、うまく機能を実装できませんでした。

下記の通り試して見たのですが、解決することができません。
ヒントや解決策をご教示いただけますと幸いです。

###困っていること
sign upをした後、送られてきたメールのリンクをクリックしてもアカウントの有効化が成功しなかった。
有効化が成功すると、「Account Activated!」と表示されるはずですが、
こちらの画像のような表示になってしまい、有効化ができない。
イメージ説明

###原因があると考えたコード(最初の行にコメントでどういった意味でコードを書いたか記入しています。)

#「userが有効化されていない状態」&「ユーザーの有効化トークンと有効化ダイジェストが一致する状態」であれば、 #アカウントの有効化が成功する。ということを記述したコードです。 class AccountActivationsController < ApplicationController def edit user = User.find_by(email: params[:email]) if user && !user.activated? && user.authenticated?(:activation, params[:id]) user.activate log_in user flash[:success] = "Account activated!" redirect_to user else flash[:danger] = "Invalid activation link" redirect_to root_url end end end
#AccountActivationsControllerに関係するモデルです。 #authenticated?メソッドとactivateメソッドの情報が必要だと思い、掲載させていただきました。 class User < ApplicationRecord attr_accessor :remember_token,:activation_token before_save :downcase_email before_create :create_activation_digest validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(.[a-z\d\-]+)*.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: true has_secure_password validates :password, presence: true, length: { minimum: 6 },allow_nil: true # 渡された文字列のハッシュ値を返す def User.digest(string) cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost BCrypt::Password.create(string, cost: cost) end # ランダムなトークンを返す def User.new_token SecureRandom.urlsafe_base64 end # 永続セッションのためにユーザーをデータベースに記憶する def remember self.remember_token = User.new_token update_attribute(:remember_digest, User.digest(remember_token)) end # 渡されたトークンがダイジェストと一致したらtrueを返す def authenticated?(attribute, token) digest = send("#{attribute}_digest") return false if digest.nil? BCrypt::Password.new(digest).is_password?(token) end def forget update_attribute(:remember_digest, nil) end def activate update_attribute(:activated, true) update_attribute(:activated_at, Time.zone.now) end # 有効化用のメールを送信する def send_activation_email UserMailer.account_activation(self).deliver_now end private # メールアドレスをすべて小文字にする def downcase_email self.email = email.downcase end # 有効化トークンとダイジェストを作成および代入する def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(activation_token) end end

###試したこと
editアクションのif文の1行目
if user && !user.activated? && user.authenticated?(:activation, params[:id])
が強制的に成功するように書き換えて見た。
( if user == userにして見た。 )

class AccountActivationsController < ApplicationController def edit user = User.find_by(email: params[:email]) if user == user user.update_attribute(:activated, true) user.update_attribute(:activated_at, Time.zone.now) log_in user flash[:success] = "Account activated!" redirect_to user else flash[:danger] = "Invalid activation link" redirect_to root_url end end end

こうした結果、下の画像のようなエラーが出ました。
userに原因があるのかなと考えているのですが、どういった原因があるのか検討がつきません。。
イメージ説明

以上でございます。
恐れ入りますが、ヒントなど頂けますと幸いでございます。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suama

2021/02/12 05:13

もしよければ、画面のエラーに出ているソースコードと、記載しているソースコードが合っていないのですが、貼り直していただけますか? AccountActivationsControllerのeditのところ。 もしキャプチャのソースのほうを優先するとして、"undefined mthod activate for nil class" というメッセージが出ているのなら、user.activate しようとしている "user" 自体がnilになっているのでは。 つまり、user = User.find_by(email: params[:email]) のところでうまくuserが取得できてないと思います。
guest

回答1

0

ベストアンサー

質問のほうに書きましたが、念のため回答の方に。

もしよければ、画面のエラーに出ているソースコードと、記載しているソースコードが合っていないのですが、貼り直していただけますか?
AccountActivationsControllerのeditのところ。
もしキャプチャのソースのほうを優先するとして、"undefined mthod activate for nil class" というメッセージが出ているのなら、user.activate しようとしている "user" 自体がnilになっているのでは。

つまり、user = User.find_by(email: params[:email]) のところでうまくuserが取得できてないと思います。

20210213: 追記

コメントいただきましたので、追記をしてみます。解決に直結しなくてすみません!
エラーのキャプチャを見ると、どんなパラメータがコントローラーに渡っているかが表示されていますね。

params -> { email: "3Drensyuu@gmail.com", id: 'xxxxx' }

という形でデータが渡っているので、確かに params[:email] でメールアドレスは取得できるかなと思います。

さて、rails console でUser.lastは確認しているとのことなので、同じように、rails consoneで User.find_by(email: "3Drensyuu@gmail.com") とした時に結果が返るでしょうか。

ただ、メールが届いているということなので、きっと存在するのでしょうけれど....。

ruby

1 def edit 2 user = User.find_by(email: params[:email]) 3 # ここをいったん書き換えてみます(user == userでなくuser.present?) 4 # present? は対象のオブジェクトがnilでないことを示します。 5 # find_byでヒットしてればnilじゃないはず 6 # デバッグできるなら binding.pry を差し込んでみましょう 7 if user.present? 8 user.update_attribute(:activated, true) 9 user.update_attribute(:activated_at, Time.zone.now) 10 log_in user 11 flash[:success] = "Account activated!" 12 redirect_to user 13 else 14 flash[:danger] = "Invalid activation link" 15 redirect_to root_url 16 end 17 end


上記に加えて、editの処理が走った時の、Rails側のログも見てみると、なにかエラーの情報などが出ているかと思います。

find_by(xxxx) を行うと、SQL のSELECT文がRails側のログに出力されます。
SELECT * FROM USERS WHERE email = '....' 的な文です。送信したときのリクエストパラメータとともに、この前後の出力でもなにかヒントがあるかもしれません。

投稿2021/02/12 11:50

編集2021/02/12 23:10
suama

総合スコア1997

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gussan-me

2021/02/12 12:55 編集

suama様ご確認いただきまして、ありがとうございます。 ソースコードに誤りがあり、申し訳ございませんでした。 AccountActivationControllerのeditアクションを修正させていただきました。 user = User.find_by(email: params[:email])のところで、 userが取得できていないとのことですが、原因はどういった所にあるのでしょうか。 自分なりに考えて、下記の通り進めて見ました。 1,sign upした後、emailの登録ができていない可能性があると考えて、もう一度sign upを行った。 2,rails console内でUser.lastを入力して、 emailカラムにsign upの時に登録したemailが登録されているか確認。 →emailカラムには、sign up時に登録したemailが登録されていた。 上記の通り、emailカラムにちゃんと登録が行われており、 どうしてeditアクション内でuserが取得できていないのか理解することができませんでした。。。 お手数をお掛けしてしまい申し訳ございませんが、こちらの件についてご教示頂けますと幸いです。 恐れ入りますが、何卒よろしくお願い致します。
suama

2021/02/12 22:49

ありがとうございます。チュートリアルの11章ですね。 エラーのキャプチャを見ると、どんなパラメータがコントローラーに渡っているかが表示されていますね。 params -> { email: “3Drensyuu@gmail.com”, id: ‘xxxxx' } rails console でUser.lastは確認しているとのことなので、同じように、rails consoneで User.find_by(email: "3Drensyuu@gmail.com") とした時に結果が返るでしょうか? このあたり、回答に追記いたしますね。
gussan-me

2021/02/13 00:03

度々ご回答いただきまして、誠にありがとうございます。 再度、下記の手順で進めさせていただきました。 ※$ rails db:resetをしてしまい、新たにsign upをして進めたので、 エラーのメールアドレスとは異なっております。 (email: rensyuu@gmail.comになりました。) 1,editアクションのif文を「if user.present?」に変更しました。 2,新たにsign upをして、rails consoeに下記の入力を致しました。  下記の通り、ちゃんと結果が返ってきました。。 > User.find_by(email: "rensyuu@gmail.com") User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "rensyuu@gmail.com"], ["LIMIT", 1]] => #<User id: 102, name: "テスト", email: "rensyuu@gmail.com", created_at: "2021-02-12 23:05:31", updated_at: "2021-02-12 23:05:31", password_digest: [FILTERED], remember_digest: nil, admin: nil, activation_digest: "$2a$12$ScQenW5q9zRn6cdGx14qk.UjAFXEPE4ayeCXl0zOHTs...", activated: false, activated_at: nil, reset_digest: nil, reset_sent_at: nil> 2.6.3 :003 > 3,railsサーバーのコンソールに表示されている有効化リンクをクリックして、 アカウントの有効化に再チャレンジを致しました。 →質問の1枚目と同様のページが表示されました。(Invalid activation link と表示されました。) このような状況で、まだ有効化が成功しません。。。 度々大変恐縮でございますが、ご確認の程よろしくお願い申し上げます。
gussan-me

2021/02/13 00:18

binding.pryも調べて使用して見ました。 userがnilとなっておりました。。 テーブルには登録されていて、そこから上手く取り出せていないのかなと思ったのですが、 なぜ取り出せないのでしょうか。。 「user = User.find_by(email: params[:email])」は、 間違いがないようにRailsチュートリアルからコピペをしているのですが。。 3: def edit 4: user = User.find_by(email: params[:email]) => 5: binding.pry 6: if user.present? 7: user.activate 8: log_in user 9: flash[:success] = "Account activated!" 10: redirect_to user 11: else 12: flash[:danger] = "Invalid activation link" 13: redirect_to root_url 14: end 15: end [1] pry(#<AccountActivationsController>)> user => nil ご確認の程、よろしくお願いいたします。
suama

2021/02/13 00:26

ちょっと進みましたね。pryできるのであれば、 params[:email] 等ってみて、中身を見てみましょう。 期待通りの値(メールアドレス)が入っていますか? また、ブレークポイントで止まっているところで、同じく User.find_by(email: params[:email]) や User.last を実行してみるとどうでしょう。
gussan-me

2021/02/13 02:29 編集

ありがとうございます。 ご教示いただいた通りに進めて見ました。 (新たにsign upしたため、id: 104、email: "rensyuu@gmai.com" となっております。) prams[:email]を出力した時は、"3Drensyuu@gmai.com"となっているのに対して、 User.lastを出力した時は"rensyuu@gmai.com"となり、先頭に3Dがついておりませんでした。 こちらが原因ということになりますでしょうか。 しかし、userに値が入っているのにも関わらず、なぜ有効化ができないのか理解することができません。。 勉強不足で申し訳ございませんが、ご教示頂けますと幸いです。 [1] pry(#<AccountActivationsController>)> params[:email] => "3Drensyuu@gmai.com" [2] pry(#<AccountActivationsController>)> User.find_by(email: params[:email]) CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "3Drensyuu@gmai.com"], ["LIMIT", 1]] ↳ (pry):2:in `edit' => nil [3] pry(#<AccountActivationsController>)> User.last User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ? [["LIMIT", 1]] ↳ (pry):3:in `edit' => #<User:0x00007f77d8ad8250 id: 104, name: "テスト2", email: "rensyuu@gmai.com", created_at: Fri, 12 Feb 2021 23:45:39 UTC +00:00, updated_at: Fri, 12 Feb 2021 23:45:39 UTC +00:00, password_digest: [FILTERED], remember_digest: nil, admin: nil, activation_digest: "$2a$12$hmDuvLqF7dkJa5B7HnzVL.b6np0BXgSfaDGlpowYqvjoVwx7hxyES", activated: false, activated_at: nil, reset_digest: nil, reset_sent_at: nil>
suama

2021/02/13 02:42

出力結果ありがとうございます!! なにかゴミデータが入っているかもしれませんね。 受け取る側の問題ではなく、アクティベーション用に生成されたメール文面で、メールアドレスの指定に間違いとか先頭に空白や記号文字列がついているのかもしれません。 (1) メールは正しく送信されて、正しい宛先に届く (2) メールのリンクをクリックすると、”3D” という文字列がくっついてコントローラにPOSTされてしまう もしこの状態なら、メールのテンプレートに空白文字や記号が入っちゃっているのかもしれません。 app/views/user_mailer/account_activation.text.erb とか app/views/user_mailer/account_activation.html.erb になると思うので、 `` edit_account_activation_url(@user.activation_token, email: @user.email) `` のところで変な文字や改行が入っていないか確認してみてくださいね。 (text用、html用双方)
gussan-me

2021/02/13 06:27

ありがとうございますm(._.)m 解決することができました!! 仰る通り、 edit_account_activation_url(@user.activation_token, email: @user.email) の途中に改行を入れてしまっておりました。 改行を入れてしまうと"3D"のような変な文字列が入ってしまうのですね。。 長々とご相談に乗っていただきまして、誠にありがとうございます。 恐れ入りますが、よろしくお願い致します。
suama

2021/02/13 06:29

良かったです! すぐ気がつけばよかったですが、こちらこそ!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問