LoginSignup
8
3

More than 3 years have passed since last update.

Mysql2::Error: Field '****' doesn't have a default valueに二回もハマった話

Posted at

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メソッドに問題が
ないか確かめましょう、、、!!!

他にもこのエラーに対する考えられる原因と、それの対処法があればコメントお願いします!!

8
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3