Mysql2::Error: Field 'tag_name' doesn't have a default value
とは、NOT NULL制約をかけているにも関わらず値が入っていないよーといった感じのエラーです
class CreateTags < ActiveRecord::Migration[6.0]
def change
create_table :tags do |t|
t.string :name,null:false
t.timestamps
end
end
end
とかでカラムに,null: falseで必ず値が入るように設定していたと思います
なので、rails側でも
validates :name,presence: true
と、バリデーションをかけていたと思います。
というわけで、まず考えられる原因が
マイグレーションファイルでnull: falseとNOT NULL制約を設けていたにも関わらず、Rails側でバリデーション をかけていなくて、form_withとか何とかで、値を保存しようとした!!
といったことが考えられます。
しかし自分は違いました、バリデーション もかけている
#[しくじった原因1: ストロングパラメーターの記述が間違ってる]
{"authenticity_token"=>"T8/aOv7fmGDk6UO/GHiYkODYvpMTH/3tFP6sCW0QPVVaAVh6ZHcAd2xaTQzcuioVXdOOWYAFNHO8u3S0OmnG6Q==",
"drink_tag"=>
{"tag_name"=>"酸味",
"image"=>
#<ActionDispatch::Http::UploadedFile:0x00007f8a24b3d318
@content_type="image/jpeg",
@headers="Content-Disposition: form-data; name=\"drink_tag[image]\"; filename=\"ethiopia.jpg\"\r\n" + "Content-Type: image/jpeg\r\n",
@original_filename="ethiopia.jpg",
@tempfile=#<File:/var/folders/34/pbcy_n7j1q79hnpm7sbcgl0m0000gn/T/RackMultipart20201204-1452-13ocgpk.jpg>>,
"name"=>"エチオピア",
"explain"=>"酸味があってアイスもおすすめ!!",
"price"=>"1000"},
"commit"=>"投稿する"}
と、パラメーターがとんでいて
private
def drink_params
params.require(:drink_tag).permit(:name,:price,:explain,:image,:tag_name).merge(user_id: current_user.id)
end
とストロングパラメーターを書くのが正しいですが
自分の場合、ストロングパラメータくらい分かったつもりになって教材をコピペしたせいで,
private
def drink_params
params.require(:tweet_tag).permit(:name,:price,:explain,:image,:tag_name).merge(user_id: current_user.id)
end
と、
params.require(:drink_tag)
を
params.require(:tweet_tag)
にしていました、、、。
ストロングパラメーターが間違っていたら
正しい値を許容できていないので
def create
@drink = DrinkTag.new(drink_params)
if @drink.save
redirect_to drinks_path
else
render 'new'
end
end
の@drinkは空,nilなので、
nilな物を保存すんな!って怒られてしまいます、、、。
form_withの使い方はあってたので、しっかりとしたパラメーターが作られて
railsのバリデーションの網はかいくぐったようですが、MySQLちゃんがしっかりと値の保存を防いでくれました、、、。
[しくじった原因2: Formオブジェクトを用いた値の保存で、一度に保存するためのmodelの記述が間違ってる!]
Formオブジェクトとは、一つのビューで複数の値を保存したいときに用いられるテクニック?的なものです。
( 詳しくは検索、検索♪)
class UserDonation
include ActiveModel::Model
attr_accessor :name, :name_reading, :nickname, :postal_code, :prefecture, :city, :house_number, :building_name, :price
with_options presence: true do
validates :name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "は全角で入力してください。"}
validates :name_reading, format: { with: /\A[ァ-ヶー-]+\z/, message: "は全角カタカナで入力して下さい。"}
validates :nickname, format: { with: /\A[a-z0-9]+\z/i, message: "は半角英数で入力してください。"}
end
def save
user = User.create(name: name, name_reading: name_reading, nickname: nickname)
Address.create(postal_code: postal_code, prefecture: prefecture, city: city, house_number: house_number,
building_name: building_name, user_id: user.id)
Donation.create(price: price, user_id: user.id)
end
end
と、一つのビューで複数のテーブルに値を保存したい時に、こういったモデルをよく作りますが
saveメソッドでのキー、バリューの書き忘れ!!!
で自分はつまずきました、、、。
この定義したsaveメソッドはあとでコントローラーで
def create
@donation = UserDonation.new(donation_params)
if @donation.valid?
@donation.save # バリデーションをクリアした時
return redirect_to root_path
else
render "new" # バリデーションに弾かれ時
end
end
とsaveメソッドを用いますが、
例えば、
def save
user = User.create(name: name, name_reading: name_reading, nickname: nickname)
Address.create(postal_code: postal_code, prefecture: prefecture, city: city, house_number: house_number,
building_name: building_name, user_id: user.id)
Donation.create(price: price, user_id: user.id)
end
で、
Address.create(postal_code: postal_code, prefecture: prefecture, city: city, house_number: house_number,
building_name: building_name, user_id: user.id)
の
postal_code: postal_code
が抜け落ちてたら、このエラーが起きます、、、。
なので、しっかりsaveメソッドが定義できてるかみましょう!!
これもフォームで入力して、しっかりパラメーターが作られるので、railsのバリデーション の
網を抜けたのでしょうが、データベース側でも「nilはだめ!!」としていたので、助かりました、。
# まとめ
バリデーション をかけているにもかかわらず、このエラーが起きるということは、モデルかコントローラーに
何かしらの問題がある。
もっというと、コントローラーは、createで値を保存するので、
ストロングパラメーターに問題があったり、
formオブジェクトはmodelにsaveメソッドを定義してるので、saveメソッドに問題が
ないか確かめましょう、、、!!!
他にもこのエラーに対する考えられる原因と、それの対処法があればコメントお願いします!!