前提
railsチュートリアルを学習中のものです。
11章の11.3のところで詰まっています。
11.3.2でeditアクションに変更を加えて、リスト11.25にかかれているURLをブラウザでアクセスしましたが、アカウントが有効化されたというページが表示されません。
実現したいこと
アカウント有効化機能を動作するようにすること
発生している問題・エラーメッセージ
エラーは出ていないのですが、有効化に失敗したときの条件分岐が動作してしまいます。
また、if文のuser.authenticated?(:activation, params[:id])という記述をdebuggerで試したときに、falseとなりました。
なのでそれに関連する箇所を一通り確認したのですが、どこに間違いがあるのかが見つかりませんでした。
app/controllers/account_activation_controllers
1class AcountActivationsController < ApplicationController 2 3def edit 4 user = User.find_by(email: params[:email]) 5 # debugger 6 if user && !user.activated? && user.authenticated?(:activation, params[:id]) 7 user.update_attribute(:activated, true) 8 user.update_attribute(:activated_at, Time.zone.now) 9 log_in user 10 flash[:success] = "Account activated!" 11 redirect_to user 12 else 13 flash[:danger] = "Invalid activation link" 14 redirect_to root_url 15 end 16 end 17 18end
該当のソースコード
app/controllers/account_activation_controller.rb
1class AcountActivationsController < ApplicationController 2 3def edit 4 user = User.find_by(email: params[:email]) 5 # debugger 6 if user && !user.activated? && user.authenticated?(:activation, params[:id]) 7 user.update_attribute(:activated, true) 8 user.update_attribute(:activated_at, Time.zone.now) 9 log_in user 10 flash[:success] = "Account activated!" 11 redirect_to user 12 else 13 flash[:danger] = "Invalid activation link" 14 redirect_to root_url 15 end 16 end 17 18end
app/controllers/users_controller.rb
1class UsersController < ApplicationController 2 def create 3 @user = User.new(user_params) 4 if @user.save 5 # log_in @user 6 # flash[:success] = "Welcome to the Sample App!" 7 UserMailer.account_activation(@user).deliver_now 8 flash[:info] = "Please check your email to active your account." 9 redirect_to root_url 10 #redirect_to @user #redirectでモデルオブジェクトを指定すると、 11 else #railsはそのモデルのidを取得し、そのidのページに移動する 12 render 'new' 13 end 14 end 15end
app/models/user.rb
1class User < ApplicationRecord 2 attr_accessor :remember_token, :activation_token 3 #remember_tokenはuserテーブルにない為、仮想的にここで定義する 4 before_save :downcase_email 5 before_create :create_activation_digest 6 7 8 # before_save { email.downcase! } メソッド参照に切り替え 9 validates :name, presence: true, length: { maximum: 50 } 10 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i 11 validates :email, presence: true, length: { maximum: 255 }, 12 format: { with: VALID_EMAIL_REGEX }, 13 uniqueness: { case_sensitive: false } 14 has_secure_password 15 validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 16 17 # 渡された文字列のハッシュ値を返す 18 def User.digest(string) 19 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 20 BCrypt::Engine.cost 21 BCrypt::Password.create(string, cost: cost) 22 end 23 24 # ランダムなトークンを返す 25 def User.new_token 26 SecureRandom.urlsafe_base64 27 end 28 29 # 永続セッションのためにユーザーをデータベースに記憶する 30 def remember 31 self.remember_token = User.new_token 32 update_attribute(:remember_digest, User.digest(remember_token)) 33 end 34 35 # 渡されたトークンがダイジェストと一致したらtrueを返す 36 def authenticated?(attribute, token) 37 digest = send("#{attribute}_digest") 38 return false if remember_digest.nil? 39 BCrypt::Password.new(digest).is_password?(token) 40 end 41 42 # ユーザーのログイン情報を破棄する 43 def forget 44 update_attribute(:remember_digest, nil) 45 end 46 47 private 48 49 # メールアドレスをすべて小文字にする 50 def downcase_email 51 email.downcase! 52 end 53 54 # 有効化トークンとダイジェストを作成および代入する 55 def create_activation_digest 56 self.activation_token = User.new_token 57 self.activation_digest = User.digest(activation_token) 58 end 59 60end
app/helpers/sessions_helper.rb
1module SessionsHelper 2 3 def log_in(user) 4 session[:user_id] = user.id 5 end 6 7 # ユーザーのセッションを永続的にする 8 def remember(user) 9 user.remember 10 cookies.permanent.encrypted[:user_id] = user.id 11 cookies.permanent[:remember_token] = user.remember_token 12 end 13 14 # 記憶トークンcookieに対応するユーザーを返す 15 def current_user 16 if (user_id = session[:user_id]) #ユーザーがログインしているとき 17 @current_user ||= User.find_by(id: user_id) 18 elsif (user_id = cookies.encrypted[:user_id]) #ユーザーがログインしていないとき 19 user = User.find_by(id: user_id) 20 if user && user.authenticated?(:remember, cookies[:remember_token]) 21 log_in user 22 @current_user = user 23 end 24 end 25 end 26end
app/mailers/application_mailer.rb
1class ApplicationMailer < ActionMailer::Base 2 default from: "example@railstutorial.org" 3 layout 'mailer' 4end
app/mailers/user_mailer.rb
1class UserMailer < ApplicationMailer 2 3 def account_activation(user) 4 @user = user #ビューで使えるようにしている 5 mail to: user.email, subject: "Account activation" #件名 6 end 7end
app/views/user_mailer/account_activation.html.erb
1<h1>Sample App</h1> 2 3<p>Hi <%= @user.name %>,</p> 4 5<p> 6Welcome to the Sample App! Click on the link below to activate your account: 7</p> 8 9<%= link_to "Activate", edit_acount_activation_url(@user.activation_token, email: @user.email) %>
app/views/user_mailer/account_activation.text.erb
1Hi <%= @user.name %> 2 3Welcome to the Sample App! Click on the link below to activate your account: 4 5<%= edit_acount_activation_url(@user.activation_token, email: @user.email) %>
test/mailers/previews/user_mailer_preview.rb
1class UserMailerPreview < ActionMailer::Preview 2 def account_activation 3 user = User.first #有効なユーザーを設定 4 user.activation_token = User.new_token #モデルで設定した仮変数に代入 5 UserMailer.account_activation(user) #メソッドに引数を与えて呼び出し 6 end 7end
サーバーログから貼り付けたURL <a href="https://17a475026ec84008aaa4a3956a5472f8.vfs.cloud9.ap-northeast-1.amazonaws.com/acount_activations/_UIfFfBrL2x6lGTRIIkq9A/edit?email=55555%40example.com">Activate</a>
試したこと
・debuggerメソッドを使用したときにuser.authenticated?(:activation, params[:id])がfalseになった。
補足情報(FW/ツールのバージョンなど)
cloud9
Rails 6.0.4
ruby 2.7.6
回答3件
あなたの回答
tips
プレビュー