Help us understand the problem. What is going on with this article?

一度の投稿で複数のモデルに保存する方法

More than 1 year has passed since last update.

今回やりたいこと

一度の投稿で複数のモデルにデータを保存したい!

背景

例えばツイッターなどで1つの投稿につき画像が複数保存される場合、image1、image2、image3・・・というカラムを作らなくてはいけなくなるため、投稿と紐ついたimageテーブルを作ることで解決しようとした。

 実装方法

①tweetモデルとimageモデルを作る
②tweetモデルを親モデルとし、imageモデルと紐つける
③viewでfields_forを使ってform_forのなかで子モデルに対してもデータが保存できるようにする
④controllerで_attibutesをつかってitemのparamsの中で一括で受け取るように記述

controller

tweets_controller
class TweetsController < ApplicationController
  def new
    @tweet = Tweet.new
    @tweet.images.build
  end

  def create
    Tweet.create(tweet_params)
  end

  private

  def tweet_params
    params.require(:tweet).permit(
      :text,
      images_attributes: {image: []}
    )
  end
end

model

親モデル

tweet.rb
class Tweet < ApplicationRecord
  has_many :images, inverse_of: :tweet
  accepts_nested_attributes_for :images
end

子モデル

image.rb
class Image < ApplicationRecord
  belongs_to :tweet, inverse_of: :images
  mount_uploaders :image, ImageUploader
end

view

new.html.haml
.contents
  = form_for @tweet do |f|
    = f.label :text, "テキスト"
    = f.text_area :text, placeholder: "ここに文字を入力してね!"
    .file
    = f.fields_for :images do |c|
      = c.label :image
      = c.file_field :image, multiple: true
    .submit
      = f.submit "投稿", {class: "btn"}

詰まったところ

paramsは送られているのにimageに保存ができない!(rollbackやエラーはなし)

理由:controllerの_attributesの書き方がわるい

誤
params.require(:tweet).permit(
      :text,
      images_attributes: [:image]
    )

正
params.require(:tweet).permit(
      :text,
      images_attributes: {image: []} 
    )

これだと一枚の場合は保存できるが、複数枚送られたときに保存ができない。

画像を保存しようとすると「no implicit conversion of nil into String」とエラーが出る。

Image from Gyazo

直訳するとnilはStringに変えれませんよ!と怒られている。
paramsにnilが入ってるのかなと思って何度もみてもnilは見つからなかった。
ググってるうちに以下の記事が救ってくれた。

・“no implicit conversion of nil into String” error for carrierwave multiple image upload
https://stackoverflow.com/questions/33401629/no-implicit-conversion-of-nil-into-string-error-for-carrierwave-multiple-image

複数画像の時はmount_uploder"s"にしないといけなかったっぽい

image.rb
一枚→ mount_uploader :image, ImageUploader

複数→ mount_uploaders :image, ImageUploader

まとめ

新しい機能を実装するときにはミニアプリを使って挙動確かめるのがおすすめ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした