railsの勉強でエラーにぶつかりまくって、パンクしそうなのでメモに残そうと思い、この記事を書きました。
同じようなエラーで困っている方の参考になれば嬉しいです。
初学者なので間違っていればご指摘お願いします。
ActiveRecord::StatementInvalid in Tasks#index
現場Railsのチャプター4が最後まで進んだので、実装できているか改めて確認しようとログインをしたらエラーが発生しました。
ActionView::Template::Error (SQLite3::SQLException: no such column: tasks.user_id: SELECT “tasks”.* FROM “tasks” WHERE “tasks”.”user_id” = ? ORDER BY “tasks”.”created_at” DESC):
no such column:tasks.user_id(user_idのカラムがないよー)とあったので、マイグレーションファイルかモデルファイルにタイプミスがあるか確認をしました。
モデルファイル
まずはモデルファイルから確認します。
class User < ApplicationRecord
has_secure_password
validates :name, presence: true
validates :email, presence: true, uniqueness: true
has_many :tasks
end
class Task < ApplicationRecord
validates :name, presence: true, length: {maximum: 30}
validate :validate_name_not_including_comma
belongs_to :user
scope :recent, -> { order(created_at: :desc) }
private
def validate_name_not_including_comma
errors.add(:name, 'にカンマを含めることはできません') if name&.include?(',')
end
end
2つとも書籍とコードを見比べてみましたが、タイプミスは見つけられませんでした。
マイグレーションファイル
次にマイグレーションファイルの確認です。
class AddUserIdToTasks < ActiveRecord::Migration[5.2]
def change
def up
execute 'DELETE FROM tasks;'
add_reference :tasks, :user, null: false, index:true # 半角スペースがない
end # index: trueに修正
def down
remove_reference :tasks, :user, index: true
end
end
end
upメソッドの「index:true」のtrueの前に半角スペースがなかったのでここか?と思い、修正後「rails db:migrate」を実行しました。
しかし、エラーは治らず…。その後、色々と調べた結果以下の手順で解決できました。
解決法
STEP1
まず、「rails db:migrate:status」でマイグレーションの状態が調べられるそうなので、コマンドを実行します。
STEP2
次に、「rails c」でコンソールを立ち上げた後に、「Task.column_names」と打つと反映されているカラム名が確認できます。
やはり、user_idカラムが追加されていませんでした。ということはデータベースにuser_idカラムがないということだから、また新しくファイルを作って追加しないといけないのか…。
でも、Add user id to tasksでuser_id追加されるんじゃないの?とモヤモヤし念のためにもう一度マイグレーションファイルを確認。
STEP3
class AddUserIdToTasks < ActiveRecord::Migration[5.2]
def change
def up
execute 'DELETE FROM tasks;'
add_reference :tasks, :user, null: false, index: true
end
def down
remove_reference :tasks, :user, index: true
end
end
end
Railsガイドから、changeメソッドの代わりにupとdownメソッドを使うことができると知りました。
もう一度確認してみると、案の定changeメソッドが残ったままでした。完全に知識不足ですね…。
STEP4
class AddUserIdToTasks < ActiveRecord::Migration[5.2]
def up
execute 'DELETE FROM tasks;'
add_reference :tasks, :user, null: false, index: true
end
def down
remove_reference :tasks, :user, index: true
end
end
はい、これが正しいコードでした。修正後はこちらもサイトなどを見て「rails db:rollback」をして前のバージョンに戻してから再度「rails db:migrate」しました。
STEP5
まずは、rollbackでバージョンを戻します。
user_idカラムと関連がある「Add user id to tasksファイル」がちゃんとdownになっているので前のバージョンに戻せています。
再度「rails db:migrate」を実行をすると、ついにログインができるようになりました!
エラーの原因
- upとdownメソッドはchangeメソッドの代わりに使っていることを知らずに、change メソッドで囲ってしまっていた。
- 半角スペースがなかったところがあった
- すでにマイグレーションしたファイルを後から修正して、そのままマイグレーションしても、内容は反映されない。一度そのファイルをrollbackでバージョンを戻してからmigrateする必要があった。
参考文献