バージョン
- ruby 3.2.2
- Rails 6.1.7.6
スクールの課題でタスク管理アプリを作成中、先にname
とcontent
のカラムを作ってあり、後で、timelimit
(終了期限)のカラムを追加した。後からカラムを追加すると、既に保存してあるデータベースについては、後から追加したカラムの値がnil
となってしまいエラーになってしまうので、デフォルト値を設定した。
しかし、新規投稿しても、終了期限が、デフォルト値で設定してある「今日」になって登録されてしまう!!なぜだ!!
schema.rb
の中身はこんな感じ↓
create_table "tasks", force: :cascade do |t|
t.string "name", null: false
t.text "content", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.date "timelimit", default: -> { "CURRENT_DATE" }, null: false
end
end
このエラー回避のため、コールバックでset_default_timelimit
メソッドを追加していたので
binding.irb
を入れて試してみる!
class Task < ApplicationRecord
before_create :set_default_timelimit
validates :name, :content, presence: true
validates :name, length: {maximum: 100}
validates :content, length: {maximum: 1000}
private
def set_default_timelimit
binding.irb
self.timelimit ||= Date.today
end
end
Unpermitted parameter: :timelimit
というエラー表示があり、
また、self
の中をチェックしてみると、
timelimit
がnil
になっている!!なぜだなぜだ!!
class TasksController < ApplicationController
# 省略
def new
@task = Task.new
end
def create
@task = Task.new(task_params)
if @task.save
redirect_to task_path(@task.id), notice: "投稿を作成しました!"
else
render :new
end
end
# 省略
private
def task_params
params.require(:task).permit(:name, :content)
end
end
問題は、このtask_params
メソッド!
params.require(:task).permit(:name, :content)
この中に、timelimit
を入れ忘れていたために、Unpermitted parameter: :timelimit
(許可されていないパラメーター、の意味)が表示された。binding.irb
で確認した時timelimit
がnil
になっているのは、パラメーターが許可されてなかったために、入力された終了期限はtimelimit
に値として入ることはできず、初期値として設定してある今日の日付がtimelimit
の値として保存されてしまうのでした。(schema.rb
参照)
ちなみに豆知識を教えてもらった!
ID
もnil
となっているのは、このbinding.irb
によってデータベースに保存される直前で止まっているから!
データベースに保存されて初めてID
が付与され保存されるので、データベースに保存される直前ではnil
になっているとのこと。おーーなるほど、面白い!
そして、後から判明したことがあった!
timelimit
に値が入らなかった時、色々試すために下記のように
class Task < ApplicationRecord
before_create :set_default_timelimit
#省略
private
def set_default_timelimit
self.timelimit ||= Date.today
end
end
app/models/task.rb
の中に、set_default_timelimit
を定義したけれど、結局は、task_params
メソッドに、timelimit
を入れ忘れていたことがtimelimit
に値が入らない要因だったわけだから、このset_default_timelimit
メソッドは消してもうまく動きました!
モヤモヤ理解だったselfについて理解できた!
でもでも、不要だったset_default_timelimit
を定義したおかげで、ずっとモヤモヤしてた self
について理解を深めることができてよかった!!
self
って、よく「それ自身」とか「そのもの」とかって説明されているけど、それ自身って何よ?っていう感じだった!
でも、実際にこうやってselfの中身を見てみると、name
は「mama」、content
は「写真購入」とデータが入っているのがわかり、ほんとだ〜それ自身だ〜そのものになってる〜、ととても感動しました!良い収穫になり、とても良かったで〜す!!😆
binding
でデータの中身を確認したりログを確認しながら勉強をしていくととっても面白いなーと強く実感することができました!!😃
本日は以上!お疲れ様でした!