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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

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

Ruby

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

Q&A

解決済

1回答

7070閲覧

【Rails5】1つのフォームで複数のモデルにデータを保存

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 5

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

Ruby

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

0グッド

0クリップ

投稿2018/11/07 05:24

###動作環境
ruby 2.4.4
Rails 5.2.0
gem 2.6.14.1
carrierwave 1.2.3

現在行っていること・問題

・Rails5を用いて、複数のモデルにデータを保存するフォームを作成中です。
・SirabasuというモデルとImageモデルがあり、1対多の関係を持っています。
・Sirabasuにレコードを1つ保存するフォーム内において、画像アップロードのfieldを記述し、その画像はImageに保存されるようにしたいです。(現状、画像は1枚としていますが、いずれは複数登録したい)
・Sirabasuにはデータが保存されているのですが、Imageには保存されませんでした。
調べた限りでの対策は行ったつもりなのですが、どうして良いかわかりません。どなたか解決策をご教授いただけないでしょうか。

参考にしたサイト

【Rails】formで複数モデル(テーブル)にレコードを登録 - teratail
一つのform_forで複数のテーブルに保存!! - Qiita

###schema(一部)

Ruby

1create_table "images", force: :cascade do |t| 2 t.string "image_path" 3 t.integer "sirabasu_id" 4 t.datetime "created_at", null: false 5 t.datetime "updated_at", null: false 6 end 7 8create_table "sirabasus", force: :cascade do |t| 9 t.string "name" 10 t.text "content" 11 t.integer "number" 12 t.datetime "created_at", null: false 13 t.datetime "updated_at", null: false 14 t.integer "userid" 15 t.integer "cid" 16 end 17

###Model(Sirabasu)

Ruby

1class Sirabasu < ApplicationRecord 2 has_many :images, dependent: :destroy 3 accepts_nested_attributes_for :images 4end

###Model(Image)

Ruby

1class Image < ApplicationRecord 2 belongs_to :sirabasu, optional: true 3end 4

ruby

1 2 def new 3 @sirabasu = Sirabasu.new 4 @sirabasu.images.build 5 end 6 7 def create 8 @sirabasu = Sirabasu.new(sirabasu_params) 9 if @sirabasu.save 10 redirect_to('/sirabasus') 11 else 12 render 'new' 13 end 14 end 15 16 def sirabasu_params 17 params.require(:sirabasu).permit(:number, :name, :content, :userid, :cid, sirabasus_attributes: [:image_path]) 18 end

###View(sirabasu#new)一部

ruby

1<%= form_for(@sirabasu) do |form| %> 2 <%= form.number_field :number %> 3 <%= form.text_field :name %> 4 <%= form.text_area :content %> 5 <%= form.fields_for :images do |i| %> 6 <%= i.file_field :image_path %> 7 <% end %> 8 <%= form.hidden_field :cid, :value => "" %> 9 <%= form.hidden_field :userid, :value => "" %> 10 <%= form.submit "登録", :class =>"link-button"%> 11<% end %>

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

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

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

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

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

guest

回答1

0

ベストアンサー

formオブジェクトというデザインパターンを使うのがいいかなと思います。フォームにActiveRecordのモデルを渡すのではなく保存に関する要件をまとめた新しいクラスを渡します。

SirabasuFormという保存のためのクラスを新たに用意します。SirabasuFormの中でSirabasuとImageのそれぞれのモデルを保存するようにします。
Controller

Ruby

1def new 2 @sirabasu_form = SirabasuForm.new #formオブジェクトパターンのためのクラスをviewでformに渡します 3end 4 5def create 6 @sirabasu_form = SirabasuForm.new(sirabasu_params) 7 if @sirabasu_form.save 8 redirect_to('/sirabasus') 9 else 10 render 'new' 11 end 12end 13 14def sirabasu_params 15 params.require(:sirabasu_form).permit(:number, :name, :content, :userid, :cid, :image_path) 16end

Model

Ruby

1class Sirabasu < ApplicationRecord 2 has_many :images, dependent: :destroy 3end

Ruby

1class Image < ApplicationRecord 2 belongs_to :sirabasu, optional: true 3end

Ruby

1class SirabasuForm 2 include ActiveModel::Model #テーブルは持ちませんがApplicationRecordのsaveメソッドなどを提供します 3 4 attr_accessor :number, :name, :content, :userid, :cid, :image_path 5 6 validates :name, :content, presence: true 7 8 def save 9 return false if invalid? #バリデーションを追加する場合はここに追加します 10 11 sirabasu = Sirabusu.new(name: name, content: content, number: number, userid: userid, cid: cid) 12 sirabusu.images.new(image_path: image_path) #この処理をimageの分だけループすれば複数保存も出ます 13 sirabusu.save 14 end 15end

View

HTML

1<%= form_with(model: @sirabasu_form, url: sirabasu_path) do |form| %> 2 <%= form.number_field :number %> 3 <%= form.text_field :name %> 4 <%= form.text_area :content %> 5 <%= form.file_field :image_path %> 6 <%= form.hidden_field :cid, :value => "" %> 7 <%= form.hidden_field :userid, :value => "" %> 8 <%= form.submit "登録", :class =>"link-button"%> 9<% end %>

hidden_fieldで入力を求めない値はコントローラで受け渡してもいいかもしれません

Ruby

1def create 2 @sirabasu_form = SirabasuForm.new(sirabasu_params.merge(cid: ***, userid: ***))

投稿2018/11/07 09:37

KiyoKuro

総合スコア51

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

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

退会済みユーザー

退会済みユーザー

2018/11/07 16:41

回答ありがとうございます。アドバイスをもとに試してみたところ、画像のアップロードに成功しました。 formオブジェクトやform_withは全く知らなかったので、参考になりました。複数の画像をアップロードする機能にはまだ挑戦していませんが、質問の件については解決したので、ひとまず安心です。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問