前提・実現したいこと
初質問です。言葉足らずなところがあるかも知れませんがご協力いただけますと幸いです。
現在rails tutorialの12章に取り組んでおります。
パスワードを再設定する為のメールを送るべく、パスワードリセットのリソース作成、Userモデルにパスワード再設定用のトークンとそれに対応するダイジェストを追加し、再設定メールのテンプレートを作成などをしました。
順調に進んでるかと思いきや、以下のエラーメッセージが解消できずに半日戦っております。
前章ではエラーが出なかったので恐らく本章でやらかしたかと思われます。
発生している問題・エラーメッセージ
Error: UserMailerTest#test_password_reset: ActionView::Template::Error: No route matches {:action=>"edit", :controller=>"account_activations", :email=>"michael@example.com", :id=>nil}, possible unmatched constraints: [:id] app/views/layouts/mailer.html.erb:9:in `_app_views_layouts_mailer_html_erb___4506527162881960628_72659080' app/mailers/user_mailer.rb:13:in `password_reset' test/mailers/user_mailer_test.rb:21:in `block in <class:UserMailerTest>'
実施したテスト("password_reset"のテストを追加したところからエラーが出始めました。コメントアウトするとパスします。)
require 'test_helper' class UserMailerTest < ActionMailer::TestCase test "account_activation" do user = users(:michael) user.activation_token = User.new_token mail = UserMailer.account_activation(user) assert_equal "Account activation", mail.subject assert_equal ["michael@example.com"], mail.to assert_equal ["noreply@example.com"], mail.from assert_match user.name, mail.body.encoded assert_match user.activation_token, mail.body.encoded assert_match CGI.escape(user.email), mail.body.encoded end test "password_reset" do user = users(:michael) user.reset_token = User.new_token mail = UserMailer.password_reset(user) assert_equal "Password reset", mail.subject assert_equal [user.email], mail.to assert_equal ["noreply@example.com"], mail.from assert_match user.reset_token, mail.body.encoded assert_match CGI.escape(user.email), mail.body.encoded end end
★app/views/layouts/mailer.html.erb
<h1>Sample App</h1> <p>Hi <%= @user.name %>,</p> <p> Welcome to the Sample App! Click on the link below to activate your account: </p> <%= link_to "Activate", edit_account_activation_url(@user.activation_token, email: @user.email) %>
★app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer def account_activation(user) @user = user mail to: user.email end def password_reset(user) @user = user mail to: user.email, subject: "Password reset" end end
★app/models/user.rb
class User < ApplicationRecord attr_accessor :remember_token, :activation_token, :reset_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: { case_sensitive: false } has_secure_password validates :password, presence: true, length: { minimum: 6 }, allow_nil: true # 渡された文字列のハッシュ値を返す def self.digest(string) cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost BCrypt::Password.create(string, cost: cost) end # ランダムなトークンを返す def self.new_token SecureRandom.urlsafe_base64 end <略> # 渡されたトークンがダイジェストと一致したらtrueを返す def authenticated?(attribute, token) digest = send("#{attribute}_digest") return false if digest.nil? BCrypt::Password.new(digest).is_password?(token) end # アカウントを有効にする def activate update_columns(activated: true, activated_at: Time.zone.now) end # 有効化用のメールを送信する def send_activation_email UserMailer.account_activation(self).deliver_now end # パスワード再設定の属性を設定する def create_reset_digest self.reset_token = User.new_token update_attribute(:reset_digest, User.digest(reset_token)) update_attribute(:reset_sent_at, Time.zone.now) end # パスワード再設定のメールを送信する def send_password_reset_email UserMailer.password_reset(self).deliver_now end private # メールアドレスをすべて小文字にする def downcase_email email.downcase! end # 有効化トークンとダイジェストを作成および代入する def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(self.activation_token) end end
★config/routes.rb
Rails.application.routes.draw do get 'password_resets/new' get 'password_resets/edit' get 'sessions/new' root 'static_pages#home' get '/help', to: 'static_pages#help' get '/about', to: 'static_pages#about' get '/contact', to: 'static_pages#contact' get '/signup', to: 'users#new' post '/signup', to: 'users#create' get '/login', to: 'sessions#new' post '/login', to: 'sessions#create' delete '/logout', to: 'sessions#destroy' resources :users resources :account_activations, only: [:edit] resources :password_resets, only: [:new, :create, :edit, :update] end
試したこと
activation_token が nil であることが原因であると思うのですが、"account_activation"のテストはパスするので、user.rb の create_activation_digest が実行されていないとしたら原因がわかりません。。
また、メールのプレビューを見ようとブラウザで http://<ホスト名>/rails/mailers/user_mailer/password_reset にアクセスすると本件と同様のエラーが確認できました。
回答1件
あなたの回答
tips
プレビュー