🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

1回答

1704閲覧

Formオブジェクトを用いた編集機能

shunxile

総合スコア26

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2021/01/30 06:08

編集2021/01/31 12:42

前提・実現したいこと

プログラミング初心者です。
画像や動画と共にメッセージを残すアプリケーションを開発中で
Formオブジェクトを用いた編集機能を実装中です。
Routing Error、paramsのmissing or empty、Couldn't find Message with 'id'=:id
とエラーを解消してきたのですが今回のエラーでどうすればいいか分かりません。
どなたかご教授お願いいたします。

発生している問題・エラーメッセージ

エラーメッセージ ActiveRecord::NotNullViolation in MessagesController#update Mysql2::Error: Field 'name' doesn't have a default value ターミナル Started PATCH "/messages/100" for ::1 at 2021-01-30 14:16:51 +0900 Processing by MessagesController#update as HTML Parameters: {"authenticity_token"=>"gM9DoUlMJ8F5/sUiOA59e4RyRgv1GPe8lD2YgHNSFCKlbD7u+b6fpftH5JvtesIgT7h8GXF8U7Wraky0JNQNFQ==", "message"=>{"title"=>"qaz123", "message"=>"wsx", "whom"=>"edc", "open_plan(1i)"=>"2022", "open_plan(2i)"=>"2", "open_plan(3i)"=>"22", "name"=>"updateテスト"}, "commit"=>"想いを更新する", "id"=>"100"} User Load (0.9ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1 Message Load (0.3ms) SELECT `messages`.* FROM `messages` WHERE `messages`.`id` = 100 LIMIT 1 ↳ app/controllers/messages_controller.rb:36:in `update' Tag Load (0.3ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` IS NULL LIMIT 1 ↳ app/models/message_tag.rb:29:in `update' (0.2ms) BEGIN ↳ app/models/message_tag.rb:29:in `update' Tag Exists? (0.2ms) SELECT 1 AS one FROM `tags` WHERE `tags`.`name` IS NULL LIMIT 1 ↳ app/models/message_tag.rb:29:in `update' Tag Create (0.5ms) INSERT INTO `tags` (`created_at`, `updated_at`) VALUES ('2021-01-30 05:16:51.237704', '2021-01-30 05:16:51.237704') ↳ app/models/message_tag.rb:29:in `update' (0.1ms) ROLLBACK ↳ app/models/message_tag.rb:29:in `update' Completed 500 Internal Server Error in 23ms (ActiveRecord: 2.5ms | Allocations: 13849) ActiveRecord::NotNullViolation (Mysql2::Error: Field 'name' doesn't have a default value): app/models/message_tag.rb:29:in `update' app/controllers/messages_controller.rb:37:in `update'

該当のソースコード

Ruby

1messages_controller.rb 2class MessagesController < ApplicationController 3 before_action :authenticate_user!, except: [:index] 4 before_action :search_message, only: [:index, :search] 5 6 def index 7 @q = Message.ransack(params[:q]) 8 @messages = Message.includes(:user).order("created_at DESC") 9 end 10 11 def new 12 @message_tag = MessageTag.new 13 end 14 15 def create 16 @message_tag = MessageTag.new(message_params) 17 if @message_tag.valid? 18 @message_tag.save 19 return redirect_to root_path 20 else 21 render :new 22 end 23 end 24 25 def show 26 @message = Message.find(params[:id]) 27 end 28 29 def edit 30 @message = Message.find(params[:id]) 31 if current_user.id != @message.user.id 32 redirect_to root_path 33 end 34 end 35 36 def update 37 @message = Message.find(params[:id]) 38 if @message_tag = MessageTag.new.update 39 return redirect_to root_path 40 else 41 render :edit 42 end 43 end 44 45 def destroy 46 @message = Message.find(params[:id]) 47 if current_user.id == @message.user.id 48 @message.destroy 49 redirect_to root_path 50 end 51 end 52 53 private 54 def message_params 55 params.require(:message_tag).permit(:title, :whom, :message, :open_plan, :name, :video, images: []).merge(user_id: current_user.id) 56 end 57end 58

Ruby

1message_tag.rb 2class MessageTag 3 4 include ActiveModel::Model 5 include ActiveModel::Attributes 6 include ActiveRecord::AttributeAssignment 7 attr_accessor :title, :whom, :open_plan, :message, :images, :video, :name, :user_id 8 9 with_options presence: true, length: { maximum: 50 } do 10 validates :title 11 validates :whom 12 end 13 14 with_options presence: true do 15 validates :message, length: { maximum: 200 } 16 validates :open_plan 17 validates :user_id 18 validates :name, length: { maximum: 20 } 19 end 20 21 def save 22 @message = Message.create(title: title, whom: whom, open_plan: open_plan, message: message, images: images, video: video, user_id: user_id) 23 tag = Tag.find_or_create_by(name: name) 24 25 @message_tag = MessageTagForm.create(message_id: message.id, tag_id: tag.id) 26 end 27 28 def update 29 @message = Message.update(title: title, whom: whom, open_plan: open_plan, message: message, images: images, video: video, user_id: user_id) 30 tag = Tag.find_or_create_by(name: name) 31 32 @message_tag = MessageTagForm.update(message_id: message.id, tag_id: tag.id) 33 end 34end

Ruby

1message.rb 2class Message < ApplicationRecord 3 belongs_to :user 4 has_many_attached :images 5 has_one_attached :video 6 has_many :message_tag_forms, dependent: :destroy 7 has_many :tags, through: :message_tag_forms 8 9 def self.search(search, id) 10 if search != "" 11 Item.joins(:tags).where(tags: {name: "#{search}"} , user_id: id) 12 else 13 Item.where(user_id: id) 14 end 15 end 16end

Ruby

1tag.rb 2class Tag < ApplicationRecord 3 has_many :messages, through: :message_tag_forms 4 has_many :message_tag_forms 5 6 validates :name, uniqueness: true 7end

Ruby

1class MessageTagForm < ApplicationRecord 2 belongs_to :message 3 belongs_to :tag 4end

Ruby

1class CreateTags < ActiveRecord::Migration[6.0] 2 def change 3 create_table :tags do |t| 4 t.string :name, null:false, uniqueness: true 5 t.timestamps 6 end 7 end 8end 9 10 11 12class CreateMessages < ActiveRecord::Migration[6.0] 13 def change 14 create_table :messages do |t| 15 t.string :title, null: false 16 t.string :whom, null: false 17 t.text :message, null: false 18 t.date :open_plan, null: false 19 t.string :encrypted_password 20 t.references :user, null: false 21 t.timestamps 22 end 23 end 24end 25 26 27 28class CreateMessageTagForms < ActiveRecord::Migration[6.0] 29 def change 30 create_table :message_tag_forms do |t| 31 t.references :message, foreign_key: true 32 t.references :tag, foreign_key: true 33 t.timestamps 34 end 35 end 36end

Ruby

1edit.html.erb 2<div class="new-message"> 3 <h1>残したい想い</h1> 4 <%= form_with model: @message, multipart: true, local: true do |f| %> 5 <%= render 'shared/error_messages', model: f.object %> 6 <div class="posting-form"> 7 <div class="form"> 8 タイトル 9 <span class="indispensable">必須</span> 10 </div> 11 <%= f.text_field :title, class:"form-title", id:"form-title", placeholder:"タイトル名(必須 50文字以内)", maxlength:"50" %> 12 <div class="form"> 13 メッセージ 14 <span class="indispensable">必須</span> 15 </div> 16 <%= f.text_area :message, class:"form-message", id:"form-message", placeholder:"メッセージ内容(必須 200文字以内)例)20年後の子供の誕生日に見て欲しい動画です。" ,rows:"5", maxlength:"200" %> 17 <div class="form"> 18 誰に対してか 19 <span class="indispensable">必須</span> 20 </div> 21 <%= f.text_field :whom, class:"form-whom", id:"form-whom", placeholder:"誰に宛てたものか(必須 50文字以内)例)20年後の子どもたちへ", maxlength:"50" %> 22 <div class="form"> 23 開封予定日 24 <span class="indispensable">必須</span> 25 </div> 26 <div class="form-open-plan"> 27 <%= raw sprintf( 28 f.date_select( 29 :open_plan, 30 class: 'open-plan-object', 31 use_month_numbers: true, 32 prompt:'--', 33 start_year: (Time.now.year), 34 end_year: (Time.now.year + 100), 35 date_separator: '%s'), 36 "<p> 年 </p>", "<p> 月 </p>") + "<p> 日 </p>" %> 37 </div> 38 <div class="form-caution"> 39 ※※※画像か動画どちらか1つの投稿にしてください。※※※ 40 </div> 41 <div class="image-form"> 42 <div class="form"> 43 届ける想い(画像) 44 </div> 45 <div class="click-upload"> 46 <p>クリックしてファイルをアップロード</p> 47 <%= f.file_field :images, name: 'message_tag[images][]', id:"form-image" %> 48 <div id="image-list"></div> 49 </div> 50 </div> 51 <div class="video-form"> 52 <div class="form"> 53 届ける想い(動画) 54 </div> 55 <div class="click-upload"> 56 <p>クリックしてファイルをアップロード</p> 57 <%= f.file_field :video, id:"form-video" %> 58 </div> 59 </div> 60 <div class="tag-form"> 61 タグ 62 </div> 63 <%= f.text_field :name, id:"form-tag", placeholder:"誕生日", maxlength:"20"%> 64 </div> 65 <div class="message-btn-contents"> 66 <%= f.submit "想いを更新する" ,class:"message-btn" %> 67 <%= link_to 'もどる', root_path, class:"back-btn" %> 68 </div> 69 <% end %> 70 71</div>
Request Parameters: {"_method"=>"patch", "authenticity_token"=>"gM9DoUlMJ8F5/sUiOA59e4RyRgv1GPe8lD2YgHNSFCKlbD7u+b6fpftH5JvtesIgT7h8GXF8U7Wraky0JNQNFQ==", "message"=>{"title"=>"qaz123", "message"=>"wsx", "whom"=>"edc", "open_plan(1i)"=>"2022", "open_plan(2i)"=>"2", "open_plan(3i)"=>"22", "name"=>"updateテスト"}, "commit"=>"想いを更新する", "id"=>"100"}

補足情報(FW/ツールのバージョンなど)

参考記事

https://teratail.com/questions/291532

https://qiita.com/Tiima/items/b14c73df98d0465cbb52

https://qiita.com/divclass123/items/34c4a5a7200238a0589c

不足情報があれば教えてください。随時追記させて頂きます。
よろしくお願いいたします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

モデルもschemaも載ってないのでエスパーモードです。
「Messaveにはnameが必須なのにそれが入っていない」
というエラーです。
def message_params と Parameters: をよく見比べてください。

投稿2021/01/30 07:52

winterboum

総合スコア23567

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shunxile

2021/01/30 09:41

>> winterboumさん 失礼いたしました。モデルとDB内容追記いたしました。
winterboum

2021/01/30 11:57

def message_params と Parameters: をよく見比べてください。
shunxile

2021/01/30 14:08

>> winterboumさん :title、:message、:whom、:open_plan、:nameと不足なくparamsにあると思うのですが何が足らないのでしょうか?
winterboum

2021/01/30 21:50

Paramaters では "message"=>{}です def message_params では params.require(:message_tag) です
shunxile

2021/01/31 02:59

>> winterboumさん params.require(:message_tag)を params.require(:message)としましたが同様のエラーが発生してしまいます。 新規投稿時のParametersと比べると確かに新規投稿時は現在"message"の部分が"message_tag"となっているので最初のfindの呼び出しの時点で間違えているという事でしょうか?
winterboum

2021/01/31 03:55

「同様」と「全く同じ」とでは状況が違います。 なので、エラーメッセージを厳密に確認してください。 その時の Parameters の確認も。 「新規投稿時のParametersと比べると確かに新規投稿時は現在"message"の部分が"message_tag"となっているので最初のfindの呼び出しの時点で間違えているという事でしょうか?」 ⇐  ここ何を聞いているのか理解出来ないです。saveの話?findの話?それが互いに関連してます?
shunxile

2021/01/31 05:02

>> winterboumさん :messageに変更時エラーメッセージは全く一緒でした。以下はParametersです。 Parameters: {"authenticity_token"=>"3XI4FNf0H3K1yuM/nj08aNo6PN5h7qHXO8mrwAE7y1/40UVbZwanFjdzwoZLSYMzEfAGzOWKBd4Enn/0Vr3SaA==", "message"=>{"title"=>"qaz123", "message"=>"wsx", "whom"=>"edc", "open_plan(1i)"=>"2022", "open_plan(2i)"=>"2", "open_plan(3i)"=>"22", "name"=>"updateテスト"}, "message_tag"=>{"images"=>[#<ActionDispatch::Http::UploadedFile:0x00007fb3b0ff3780 @tempfile=#<Tempfile:/var/folders/pg/6dn2c_091hb4pfr45vz6w9fr0000gn/T/RackMultipart20210131-37437-1wjehwp.jpg>, @original_filename="717Z-iIrpgL._AC_SY879_.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"message_tag[images][]\"; filename=\"717Z-iIrpgL._AC_SY879_.jpg\"\r\nContent-Type: image/jpeg\r\n">]}, "commit"=>"想いを更新する", "id"=>"100"} Parametersでは:message、def message_paramsでは:message_tagとご指摘頂いたので新規投稿は正常に動作ていたので新規投稿時のParametersではどのようになっているのだろうと確認したところ:message_tagとなっていました。 しかし現在の編集時のParametersでは:messageなのでupdateとcreate時で何か違いがあるのではないかと思いupdate内の@message=Message.find(params[:id])が間違えているのではないかと思い聞きました。
winterboum

2021/01/31 06:31

new と edit で動きが異なるとすると、viewに問題がありそうですね
shunxile

2021/01/31 07:01 編集

>> winterboumさん そうですよね..... 追記しようとしましたが文字制限でできなかったので2つのviewページの違う箇所を抜粋します。 editとnewのhtml.erbを比べると違いがあるのが1箇所でした。 3行目 new:<%= form_with model: @message, url: messages_path, local: true do |f| %> edit:<%= form_with model: @message, url: message_path(@message.id), method: :patch, multipart: true, local: true do |f| %>
winterboum

2021/01/31 07:32

両方共、urlは不要です。@messageをみてRailsが適切に計らいます。methodも。 で、 new は @message = MessageTag.new edit は @message = Message.find(params[:id]) 違うものですね。 で、 MessageTag.new なら @message_tag としないとcode読む他人は間違えます。
shunxile

2021/01/31 09:36

>> winterboumさん url・methodは削除済で正常に動作することも確認しました。ありがとうございます。 newは@message_tagに変更しました。 イメージでは@messageにMessage.findで編集したい情報を呼び出してFormオブジェクトを用いてupdateで更新すると思って @message = Message.find(params[:id]) @message = Message.create(title: title, whom: whom, open_plan: open_plan, message: message, images: images, video: video, user_id: user_id) tag = Tag.find_or_create_by(name: name) @message_tag = MessageTagForm.create(message_id: message.id, tag_id: tag.id) という流れにしたのですが違いましたでしょうか? 現状コード編集した内容に追記しましたがエラー内容もParameres:も変化がありませんでした。
winterboum

2021/01/31 11:13

updateといいながらcreateしてるように見えますが
shunxile

2021/01/31 11:54

>> winterboumさん このエラーより前にupdateが未定義ですというエラーとなり定義してもエラー内容等全く変わらなかったので今のようになっていました。 現在以下のように修正しましたがエラー内容、Parameters:共に全く変化はありませんでした。 def update @message = Message.update(title: title, whom: whom, open_plan: open_plan, message: message, images: images, video: video, user_id: user_id) tag = Tag.find_or_create_by(name: name) @message_tag = MessageTagForm.update(message_id: message.id, tag_id: tag.id) end tag = Tag.find_or_create_by(name: name)が間違っているのでしょうか? tag = Tag.update(name: name)とするとエラー内容が Mysql2::Error: Column 'name' cannot be nullと変化しました。
winterboum

2021/01/31 12:26

読みにくい、質問欄を編集して
shunxile

2021/01/31 12:43

>> winterboumさん 編集しました。
winterboum

2021/01/31 13:29

同じことを何度も書かせないで。 def edit @message = Message.find(params[:id]) だから Parameters:が {"message"=>{}} になるので def message_params で params.require(:message_tag) が nil になるの。
shunxile

2021/01/31 15:27 編集

>> winterboumさん 申し訳ありません。 つまりどのようにすればよろしいのでしょうか?
winterboum

2021/01/31 23:00

案1-1 create_params と update_params を作る 案1-2 message_params(:message), message_params(:message_tag) と使い分けるように直す 案2 edit でも message_tag を渡す。 どの案にしても「、paramsのmissing or empt」はなくなりますが、正しいMessageをupdateするというところでひと工夫が必要になりそう。 「Formオブジェクト」を使う気になったその原典に戻ってじっくり読みなおしたほうが良いですよ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問