質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Ruby on Rails

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

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Q&A

1回答

1158閲覧

一括データを保存する方法

yyu202

総合スコア2

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Ruby on Rails

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

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

0グッド

0クリップ

投稿2020/11/05 02:14

編集2020/11/06 01:35

レシピ投稿サイトを作っています。
投稿ページで材料(material)を入力した分だけ一括でテーブルに保存できるように
しようと思っています。

【Rails 6】form_with用いて一括登録する

上記サイトを参考にしてコードを書いています。
それから複数のテーブルにも保存できるような形にしています。

class Recipe < ApplicationRecord belongs_to :user has_one_attached :image has_one :chef has_many :material end
class Material < ApplicationRecord belongs_to :recipe end
class Chef < ApplicationRecord belongs_to :recipe end
class Form::Base include ActiveModel::Model include ActiveModel::Callbacks include ActiveModel::Validations include ActiveModel::Validations::Callbacks include ActiveModel::Attributes end
class Form::CookRecipe < Form::Base include ActiveModel::Model FORM_COUNT = 3 attr_accessor :video, :title, :text, :image, :user_id, :cook_1, :cooks with_options presence: true do validates :video validates :title validates :text validates :image end def initialize(attributes = {}) super attributes self.cooks = FORM_COUNT.times.map { Material.new() } unless self.cooks.present? end def cooks_attributes=(attributes) self.cooks = attributes.map { |_, v| Material.new(v) } end def save recipe = Recipe.create(user_id: user_id, video: video, title: title, text: text, image: image) Chef.create(cook_1: cook_1, recipe_id: recipe.id) Material.transaction do self.cooks.map(&:save!) end return true rescue => e return false end end
class RecipesController < ApplicationController def index @recipes = Recipe.all end def new @cook_recipe = Form::CookRecipe.new end def create @cook_recipe = Form::CookRecipe.new(recipe_params) url = params[:form_cook_recipe][:video] url = url.last(11) @cook_recipe.video = url if @cook_recipe.save redirect_to root_path else render :new end end def show @recipe = Recipe.find(params[:id]) end private def recipe_params params.require(:form_cook_recipe).permit(:video, :title, :text, :image, :cook_1, cooks_attributes: [:vegetable_1]).merge(user_id: current_user.id) end end
<h2 class="page-heading">簡単レシピ投稿</h2> <%= form_with model: @cook_recipe, url: recipes_path, local: true do |f|%> <div class="field"> <%= f.label :title, "料理名" %><br /> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :text, "説明文" %><br /> <%= f.text_area :text, class: :form__text %> </div> <%= f.fields_for :cooks do |field| %> <div class="field"> <%= field.label :vegetable_1, "材料" %><br /> <%= field.text_area :vegetable_1, class: :form__text %> </div> <% end %> <div class="field"> <%= f.label :cook_1, "作り方" %><br /> <%= f.text_area :cook_1, class: :form__text %> </div> <div class="field"> <%= f.label :image, "料理の画像" %><br /> <%= f.file_field :image %> </div> <div class="field"> <%= f.label :video, "Youtube URL" %><br /> <%= f.text_field :video %> </div> <div class="actions"> <%= f.submit "投稿", class: :form__btn %> </div> <% end %>

解決したいこと

パラメーターは送信できるのですが、一括保存をしたいMaterialテーブルにだけ保存ができません。
↓パラメーターの送信状況です。

10: def create 11: @cook_recipe = Form::CookRecipe.new(recipe_params) 12: url = params[:form_cook_recipe][:video] 13: url = url.last(11) 14: @cook_recipe.video = url => 15: binding.pry 16: 17: if @cook_recipe.save 18: redirect_to root_path 19: else 20: render :new 21: end 22: end [1] pry(#<RecipesController>)> params => <ActionController::Parameters {"authenticity_token"=>"m9wXOBjyMuu/aZOcthfY2WhpF8dy/Xsc1pQkKj9MTP7Ufty6K3npGknmuBpErMD7Upd+Mr35cR7fR2imElB61A==", "form_cook_recipe"=><ActionController::Parameters {"title"=>"pooppopopo", "text"=>"tatatatatatatattata", "cooks_attributes"=>{"0"=>{"vegetable_1"=>"ko"}, "1"=>{"vegetable_1"=>"mu"}, "2"=>{"vegetable_1"=>"gi"}}, "cook_1"=>"eeeeee", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007feb02897d90 @tempfile=#<Tempfile:/var/folders/vq/prgw2yxj1ns327cvwpw4plrc0000gn/T/RackMultipart20201105-1740-xxn2lg.jpg>, @original_filename="7ac726af05cc3a5a5cdea8819379ede6.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"form_cook_recipe[image]\"; filename=\"7ac726af05cc3a5a5cdea8819379ede6.jpg\"\r\nContent-Type: image/jpeg\r\n">, "video"=>"VgmYtFxp-SY"} permitted: false>, "commit"=>"投稿", "controller"=>"recipes", "action"=>"create"} permitted: false> [2] pry(#<RecipesController>)> @cook_recipe => #<Form::CookRecipe:0x00007feaffbeeb40 @attributes=#<ActiveModel::AttributeSet:0x00007feaffbeea28 @attributes={}>, @cook_1="eeeeee", @cooks= [#<Material:0x00007feaffc06790 id: nil, vegetable_1: "ko", vegetable_2: nil, vegetable_3: nil, vegetable_4: nil, vegetable_5: nil, vegetable_6: nil, vegetable_7: nil, vegetable_8: nil, vegetable_9: nil, vegetable_10: nil, vegetable_11: nil, vegetable_12: nil, vegetable_13: nil, vegetable_14: nil, vegetable_15: nil, recipe_id: nil, created_at: nil, updated_at: nil>, #<Material:0x00007feb099f41f0 id: nil, vegetable_1: "mu", vegetable_2: nil, vegetable_3: nil, vegetable_4: nil, vegetable_5: nil, vegetable_6: nil, vegetable_7: nil, vegetable_8: nil, vegetable_9: nil, vegetable_10: nil, vegetable_11: nil, vegetable_12: nil, vegetable_13: nil, vegetable_14: nil, vegetable_15: nil, recipe_id: nil, created_at: nil, updated_at: nil>, #<Material:0x00007feafc7d3ae0 id: nil, vegetable_1: "gi", vegetable_2: nil, vegetable_3: nil, vegetable_4: nil, vegetable_5: nil, vegetable_6: nil, vegetable_7: nil, vegetable_8: nil, vegetable_9: nil, vegetable_10: nil, vegetable_11: nil, vegetable_12: nil, vegetable_13: nil, vegetable_14: nil, vegetable_15: nil, recipe_id: nil, [3] pry(#<RecipesController>)> exit

どうにか保存できる形にしたいです。

どの点が不足しているなどご指摘いただけますでしょうか。
恐縮ですがお力を貸していただけますと幸いです。
よろしくお願いいたします。

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

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

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

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

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

winterboum

2020/11/05 08:36

パラメーター達は画像でなく<code>を使ってtextで載せてください。読みにくいし検索もできない。
guest

回答1

0

paramater は
"form_cook_recipe"=>{ "cooks_attributes"=>{} }
という構造をしています。
「Materialテーブル」へのpramsがないのでMaterialには入りません

投稿2020/11/06 02:31

winterboum

総合スコア23347

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

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

yyu202

2020/11/06 04:08

ご回答ありがとうございます。 勉強不足で申し訳ないのですが、 Materialテーブルへのparamsはcooks_attributeに入っていると思っているのですが違うのでしょうか? ``` "cooks_attributes"=>{"0"=>{"vegetable_1"=>"ko"}, "1"=>{"vegetable_1"=>"mu"}, "2"=>{"vegetable_1"=>"gi"}} ``` もしくはform_cook_recipeの中にcooks_attributesが含まれているからダメなのであり、 cooks_attributesというパラメーターを作り、 "cooks_attributes"=>{ "vegetable_1"=>ko } という形にすれば良いということですか?
winterboum

2020/11/06 09:13

Form::CookRecipe なんですね。 そうしますと  class Form::CookRecipe の initialize で期待される内容で作られているか と def save のcodeの動き の確認をしてください
yyu202

2020/11/09 09:08

たびたびすみません Material.transaction do self.cooks.map(&:save!) end return true rescue => e return false end このコードが例外が発生する可能性の処理(Material.transaction do)を行っていて、 self.cooks.map(&:save!)がcooksに保存されている配列の数だけ処理(map)を行い、 保存できるかの判断(&:save!)を行っているのだと思います。 しかし、繰り返し処理をしたところで"vegetable_1"に保存するよう記載していないから 保存がされないのでしょうか? どうしてもわかりません。 よろしくお願いします。
winterboum

2020/11/09 09:54

そのsave!が一つでも失敗すると全部なかったことになります。 どんなエラーが起きているのかを表示するようにするか、 transactionを一時的になしにしてFATALした時のエラーを見るか して何が問題でsave失敗しているのか確認しましょう。
yyu202

2020/11/10 07:13

レシピを投稿したときのログです↓ Started POST "/recipes" for ::1 at 2020-11-10 15:59:08 +0900 Processing by RecipesController#create as HTML Parameters: {"authenticity_token"=>"E/+J4Wpmtxx7pil7WtstB5r1YWVGvfdpR4bAxHQboTXxXaR5dxy0NZEewlRBd3frXjWwhdYqvvzkU+r/Xelq6w==", "form_cook_recipe"=>{"title"=>"パスタ", "text"=>"麦", "cooks_attributes"=>{"0"=>{"vegetable_1"=>"こ"}, "1"=>{"vegetable_1"=>"む"}, "2"=>{"vegetable_1"=>"ぎ"}}, "cook_1"=>"練る", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007f8679bb7b08 @tempfile=#<Tempfile:/var/folders/vq/prgw2yxj1ns327cvwpw4plrc0000gn/T/RackMultipart20201110-5698-16jbjtj.jpg>, @original_filename="houston-rockets-logo-300.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"form_cook_recipe[image]\"; filename=\"houston-rockets-logo-300.jpg\"\r\nContent-Type: image/jpeg\r\n">, "video"=>"https://www.youtube.com/watch?v=deenR1ZEKcY"}, "commit"=>"投稿"} User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1 ↳ app/controllers/recipes_controller.rb:32:in `recipe_params'  (0.2ms) BEGIN ↳ app/models/form/cook_recipe.rb:24:in `save' User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 ↳ app/models/form/cook_recipe.rb:24:in `save' Recipe Create (1.4ms) INSERT INTO `recipes` (`video`, `title`, `text`, `user_id`, `created_at`, `updated_at`) VALUES ('deenR1ZEKcY', 'パスタ', '麦', 1, '2020-11-10 06:59:08.921405', '2020-11-10 06:59:08.921405') ↳ app/models/form/cook_recipe.rb:24:in `save' ActiveStorage::Blob Load (0.6ms) SELECT `active_storage_blobs`.* FROM `active_storage_blobs` INNER JOIN `active_storage_attachments` ON `active_storage_blobs`.`id` = `active_storage_attachments`.`blob_id` WHERE `active_storage_attachments`.`record_id` = 10 AND `active_storage_attachments`.`record_type` = 'Recipe' AND `active_storage_attachments`.`name` = 'image' LIMIT 1 ↳ app/models/form/cook_recipe.rb:24:in `save' ActiveStorage::Attachment Load (0.3ms) SELECT `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_id` = 10 AND `active_storage_attachments`.`record_type` = 'Recipe' AND `active_storage_attachments`.`name` = 'image' LIMIT 1 ↳ app/models/form/cook_recipe.rb:24:in `save' ActiveStorage::Blob Create (0.3ms) INSERT INTO `active_storage_blobs` (`key`, `filename`, `content_type`, `metadata`, `byte_size`, `checksum`, `created_at`) VALUES ('yha85yimb150r4wrczijb7gpreea', 'houston-rockets-logo-300.jpg', 'image/jpeg', '{\"identified\":true}', 22989, 'rikat4xKfxIukafRq3EC8A==', '2020-11-10 06:59:08') ↳ app/models/form/cook_recipe.rb:24:in `save' ActiveStorage::Attachment Create (0.3ms) INSERT INTO `active_storage_attachments` (`name`, `record_type`, `record_id`, `blob_id`, `created_at`) VALUES ('image', 'Recipe', 10, 6, '2020-11-10 06:59:08') ↳ app/models/form/cook_recipe.rb:24:in `save' Recipe Update (0.3ms) UPDATE `recipes` SET `recipes`.`updated_at` = '2020-11-10 06:59:08.984303' WHERE `recipes`.`id` = 10 ↳ app/models/form/cook_recipe.rb:24:in `save'  (0.3ms) COMMIT ↳ app/models/form/cook_recipe.rb:24:in `save'  Disk Storage (4.5ms) Uploaded file to key: yha85yimb150r4wrczijb7gpreea (checksum: rikat4xKfxIukafRq3EC8A==) [ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: b8084dc8-28a3-47da-b812-58137638566f) to Async(active_storage_analysis) with arguments: #<GlobalID:0x00007f867273ec90 @uri=#<URI::GID gid://cook-pro/ActiveStorage::Blob/6>>  (0.6ms) BEGIN ↳ app/models/form/cook_recipe.rb:26:in `save'  (0.3ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 Recipe Load (3.1ms) SELECT `recipes`.* FROM `recipes` WHERE `recipes`.`id` = 10 LIMIT 1 ↳ app/models/form/cook_recipe.rb:26:in `save' ActiveStorage::Blob Load (15.0ms) SELECT `active_storage_blobs`.* FROM `active_storage_blobs` WHERE `active_storage_blobs`.`id` = 6 LIMIT 1 [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f] Performing ActiveStorage::AnalyzeJob (Job ID: b8084dc8-28a3-47da-b812-58137638566f) from Async(active_storage_analysis) enqueued at 2020-11-10T06:59:08Z with arguments: #<GlobalID:0x00007f867a977f68 @uri=#<URI::GID gid://cook-pro/ActiveStorage::Blob/6>> Chef Create (5.3ms) INSERT INTO `chefs` (`cook_1`, `recipe_id`, `created_at`, `updated_at`) VALUES ('練る', 10, '2020-11-10 06:59:09.056121', '2020-11-10 06:59:09.056121') ↳ app/models/form/cook_recipe.rb:26:in `save' [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f]  Disk Storage (0.6ms) Downloaded file from key: yha85yimb150r4wrczijb7gpreea  (33.0ms) COMMIT ↳ app/models/form/cook_recipe.rb:26:in `save' Rendering recipes/new.html.erb within layouts/application Rendered recipes/new.html.erb within layouts/application (Duration: 3.2ms | Allocations: 1043) [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f]  (0.3ms) BEGIN [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f] ActiveStorage::Blob Update (2.9ms) UPDATE `active_storage_blobs` SET `active_storage_blobs`.`metadata` = '{\"identified\":true,\"width\":800,\"height\":300,\"analyzed\":true}' WHERE `active_storage_blobs`.`id` = 6 [Webpacker] Everything's up-to-date. Nothing to do [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f]  (1.4ms) COMMIT [ActiveJob] [ActiveStorage::AnalyzeJob] [b8084dc8-28a3-47da-b812-58137638566f] Performed ActiveStorage::AnalyzeJob (Job ID: b8084dc8-28a3-47da-b812-58137638566f) from Async(active_storage_analysis) in 104.5ms Completed 200 OK in 261ms (Views: 63.8ms | ActiveRecord: 46.4ms | Allocations: 66805) transactionをcreateに変えたり削除したり、他のテーブルの保存方法の書き方をするなどしてみたのですが、Materialのエラーログが表示されません。 上記のログはtransactionをcreateに変えたときのログです。 自分の認識ではtransactionは失敗したときの元の状態に戻してしまうものなのでcreateにすることにより 元に戻す処理をなくすことによりログが表示されるのかと思ったのですがうまくいきませんでした。 エラーログの表示方法をご教授頂けませんか。。。 聞いてばかりですみません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問