転職活動用の個人アプリを作成しています。
食べたものやカロリー値などを投稿してカロリーコントロールしやすくするためのダイエットアプリを作成しています。
カロリー値やPFC値をpostモデルに保存するのと同時に、画像はimageモデルに保存したいのですが、それができずに困っています。
ビューの書き方も間違っていて、表示ができないのはあとで自分で考えて修正しますが、それ以前にMySQLに保存する段階でつまずいているので、まずそこの解決するためのヒントを頂ければ幸いです。
よろしくお願いします。
前提・実現したいこと
画像を保存できるようにしたい。
images_attributesを使って、カロリー値やPFC値を投稿するときに、画像データはpostモデルに紐づく形でimageモデルに保存できるようにしたい。
発生している問題・エラーメッセージ
投稿データがpostモデルに保存されるのと同時に、画像データはimageモデルに保存されるようにしたいのにできない。
imagesテーブルのimageカラムがnilになってしまう。
ターミナル
pry(#<PostsController>)> @post.images Image Load (0.4ms) SELECT `images`.* FROM `images` WHERE `images`.`post_id` = 167 ↳ app/controllers/posts_controller.rb:33 => [#<Image:0x00007fdeaf3c5650 id: 23, image: nil, post_id: 167, created_at: Sun, 16 Aug 2020 09:33:38 UTC +00:00, updated_at: Sun, 16 Aug 2020 09:33:38 UTC +00:00>]
該当のソースコード
コントローラー(posts_controller.rb)
def index @posts = Post.all.includes(:user).order("created_at DESC").page(params[:page]).per(5) @post = Post.new @post.images.build end def create @post = Post.new(post_params) if @post.save redirect_back(fallback_location: root_path) else @posts = Post.includes(:user) flash.now[:alert] = '必須項目をしてください。' redirect_back(fallback_location: root_path) end end private def post_params params.require(:post).permit(:food, :calorie, :protein, :fat, :carbo, :text, images_attributes: [:image]).merge(user_id: current_user.id) end
indexアクションでは、@post.images.build
で@postに紐づく形でimageを保存するための空き箱を作ります。
createアクションでは、form_withで入力された情報をプライベートメソッドのpost_paramsで受け取って、@postに代入しています。
この時、post_paramsのimages_attributes: [:image]
で画像データも一緒に保存されるはずなのですが、実際は保存されてくれません。
postモデル(post.rb)
class Post < ApplicationRecord has_many :images, dependent: :destroy accepts_nested_attributes_for :images, allow_destroy: true end
ビュー(_main.html.haml)
.main .section .new-post = form_with model: @post, id: 'new_post' do |f| .input-box (省略) .icon .image-upload = f.fields_for :images do |image| %i.fa.fa-camera.fa-2x = image.file_field :image, multiple: true, class: 'image_upload' .btn-square = f.submit '投稿する', class: 'post-btn'
親モデルにaccepts_nested_attributes_for: 〇〇(子モデルのテーブル名)と書くと、親モデルの情報と一緒にその子モデルの情報も保存されます。
今回で言うと親モデル(postモデル)の情報(投稿データ。食べたもの、カロリー値など)と同時に画像データは子モデル(imageモデル)に別で保存されます。
参考にしたページhttps://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
imageモデル(image.rb)
class Image < ApplicationRecord belongs_to :post mount_uploader :image, ImageUploader end
CarrierWaveを使って画像をアップロードしたい場合、画像を保存するテーブル(今回はimagesテーブル)に追加したカラムの名前をmount_uploaderに指定する。
試したこと
paramsの中身とpost_paramsの中身を確認した。
その結果、paramsでは画像データ(image5.png)が入っていたが、post_paramsには画像データが入ってなかった。
ターミナル
pry(#<PostsController>)> params => <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"h63zuMZOESYUInxzZD8jFqMbInn7kkMcWj1auQF2Irl1agWdILfmE8SEX9gYsvobDQbcAe336Nsu4SRCHezT7w==", "post"=><ActionController::Parameters {"food"=>"うどん", "calorie"=>"10", "protein"=>"10", "fat"=>"10", "carbo"=>"10", "text"=>"うどんを食べました。", "images_attributes"=>{"0"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x00007fdea83150b8 @tempfile=#<Tempfile:/var/folders/sy/26p55v5j47s2zjd8h7vr8f6h0000gn/T/RackMultipart20200816-2275-g3cxd2.png>, @original_filename="image5.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"post[images_attributes][0][image][]\"; filename=\"image5.png\"\r\nContent-Type: image/png\r\n">]}}} permitted: false>, "commit"=>"投稿する", "controller"=>"posts", "action"=>"create"} permitted: false> [2] pry(#<PostsController>)> post_params Unpermitted parameter: :image => <ActionController::Parameters {"food"=>"うどん", "calorie"=>"10", "protein"=>"10", "fat"=>"10", "carbo"=>"10", "text"=>"うどんを食べました。", "images_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {} permitted: true>} permitted: true>, "user_id"=>17} permitted: true>
わからないこと・疑問点
なぜparamsには画像データが入っているのに、post_paramsでは画像データが入っていないのか?
→paramsには問題なく入るのは、form_withのフォームで投稿してるから。paramsには入ってるのにpost_paramsには入っていないということは、posts_controllerのプライベートメソッドpost_paramsのimages_attributes: [:image]この部分の書き方が間違っているのか?
posts_controller.rb
private def post_params params.require(:post).permit(:food, :calorie, :protein, :fat, :carbo, :text, images_attributes: [:image]).merge(user_id: current_user.id) end
補足情報(FW/ツールのバージョンなど)
Ruby 2.5.1
Rails 5.2.4.3
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/16 12:47
2020/08/16 12:58
2020/08/16 13:09