20
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-02-23

今回やりたいこと

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

背景

例えばツイッターなどで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

まとめ

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

20
40
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
20
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?