#分からないこと
railsチュートリアルの演習でマイクロポストの作成を行っているのですが、root_urlに移動すると
StandardError An error has occurred, this and all later migrations canceled: SQLite3::SQLException: duplicate column name: reset_sent_at
とエラーが表示されてしまいます。
Userのreset_sent_atカラムが重複しているというのはわかるのですが、どこがどう重複しているのかがいまいちわかりません。このエラーの解決方法についてどなたかアドバイスをいただければありがたいです。
#関連しそうなファイル
#app/models/user.rb class User < ApplicationRecord has_many :microposts attr_accessor :remember_token, :activation_token, :reset_token before_save { email.downcase! } before_create :create_activation_digest validates :name, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[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?(remember_token) return false if remember_digest.nil? BCrypt::Password.new(remember_digest).is_password?(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 # パスワード再設定の属性を設定する def create_reset_digest self.reset_token = User.new_token update_columns(reset_digest: User.digest(reset_token), reset_sent_at: Time.zone.now) end # パスワード再設定のメールを送信する def send_password_reset_email UserMailer.password_reset(self).deliver_now end # パスワード再設定の期限が切れている場合はtrueを返す def password_reset_expired? reset_sent_at < 2.hours.ago 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
#app/controllers/password_resets_controller.rb class PasswordResetsController < ApplicationController before_action :get_user, only: [:edit, :update] before_action :valid_user, only: [:edit, :update] before_action :check_expiration, only: [:edit, :update] def new end def create @user = User.find_by(email: params[:password_reset][:email].downcase) if @user @user.create_reset_digest @user.send_password_reset_email flash[:info] = "Email sent with password reset instructions" redirect_to root_url else flash.now[:danger] = "Email address not found" render 'new' end end def edit end def update if params[:user][:password].empty? @user.errors.add(:password, :blank) render 'edit' elsif @user.update(user_params) log_in @user @user.update_attribute(:reset_digest, nil) flash[:success] = "Password has been reset." redirect_to @user else render 'edit' end end private def user_params params.require(:user).permit(:password, :password_confirmation) end # beforeフィルタ def get_user @user = User.find_by(email: params[:email]) end # 正しいユーザーかどうか確認する def valid_user unless (@user && @user.activated? && @user.authenticated?(:reset, params[:id])) redirect_to root_url end end # トークンが期限切れかどうか確認する def check_expiration if @user.password_reset_expired? flash[:danger] = "Password reset has expired." redirect_to new_password_reset_url end end end
#config/routes.rb Rails.application.routes.draw do get 'password_resets/new' get 'password_resets/edit' 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' 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
#app/mailers/user_mailer.rb class UserMailer < ApplicationMailer def account_activation(user) @user = user mail to: user.email, subject: "Account activation" end def password_reset(user) @user = user mail to: user.email, subject: "Password reset" end end
#20201223140935_add_reset_to_users.rb class AddResetToUsers < ActiveRecord::Migration[6.0] def change add_column :users, :reset_digest, :string add_column :users, :reset_sent_at, :datetime end end
#20201223141905_add_reset_sent_at_to_users.rb class AddResetSentAtToUsers < ActiveRecord::Migration[6.0] def change add_column :users, :reset_sent_at, :datetime end end
#db/schema.rb ActiveRecord::Schema.define(version: 2020_12_26_033956) do create_table "microposts", force: :cascade do |t| t.text "content" t.integer "user_id", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at" t.index ["user_id"], name: "index_microposts_on_user_id" end create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "password_digest" t.string "remember_digest" t.boolean "admin", default: false t.string "activation_digest" t.boolean "activated", default: false t.datetime "activated_at" t.string "reset_digest" t.datetime "reset_sent_at" t.index ["email"], name: "index_users_on_email", unique: true end add_foreign_key "microposts", "users" end
#試したこと
rails db:test:prepare
rails db:migrate RAILS_ENV=development
rails db:migrate:reset
20201223140935_add_reset_to_users.rb
20201223141905_add_reset_sent_at_to_users.rb
db/schema.rb
のreset_sent_atの部分をコメントアウトしてみる
=>root_urlにアクセスできたがパスワードリセット画面へ遷移するときエラーが起きた
#環境
CentOS8
#Gemfile source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } gem 'rails', '6.0.3' gem 'bcrypt', '3.1.13' gem 'faker', '2.1.2' gem 'will_paginate', '3.1.8' gem 'bootstrap-will_paginate', '1.0.0' gem 'bootstrap-sass', '3.4.1' gem 'puma', '4.3.6' gem 'sass-rails', '5.1.0' gem 'webpacker', '4.0.7' gem 'turbolinks', '5.2.0' gem 'jbuilder', '2.9.1' gem 'bootsnap', '1.4.5', require: false group :development, :test do gem 'sqlite3', '1.4.1' gem 'byebug', '11.0.1', platforms: [:mri, :mingw, :x64_mingw] end group :development do gem 'web-console', '4.0.1' gem 'listen', '3.1.5' gem 'spring', '2.1.0' gem 'spring-watcher-listen', '2.0.1' end group :test do gem 'capybara', '3.28.0' gem 'selenium-webdriver', '3.142.4' gem 'webdrivers', '4.1.2' gem 'rails-controller-testing', '1.0.4' gem 'minitest', '5.11.3' gem 'minitest-reporters', '1.3.8' gem 'guard', '2.16.2' gem 'guard-minitest', '2.4.6' end group :production do gem 'pg', '1.1.4' end # Windows ではタイムゾーン情報用の tzinfo-data gem を含める必要があります gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/26 14:57
2020/12/26 23:14
2020/12/27 05:03
2020/12/27 06:22
2020/12/27 07:52
2020/12/27 08:51
2020/12/27 10:02