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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

1374閲覧

fields_forを複製、初期化

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 5

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2020/11/15 22:39

編集2020/11/15 22:45

前提・実現したいこと

複数の場所の情報を持った投稿を作成する機能を実装したいです。(1つのpostに対して複数のspot)
そのために、
①新規投稿フォームの一部(fields_for部分)を複製し、値を初期化した状態で配置
②コピー元のフォームも含めて、fields_forのデータをすべて別のレコードとして保存
という処理を行いたいのですが、方法がわからずハマっています。

具体的には、
「フォームを追加」をクリックすると、fields_forを囲った<div>のクローンが、入力された値が初期化された状態で下に追加される。
「投稿」ボタンをクリックしたときに、ページ内のすべてのフォームのデータが保存される(postとそれに紐付いたspotすべて)。というのを想定しています。

spotモデルには、post_id属性を持たせており、同一のpost_idを持ったレコードは1つのpostに紐付いている状態です。

発生している問題・エラーメッセージ

現状のコードでは、
・追加されたフォームには、コピー元のフォームに入力された値が残った状態で追加される
・フォームを追加した場合、最後に追加されたフォームのデータしか保存されない
(コピー元や、コピー元と最後のフォームに挟まれたフォームが保存されない)

該当のソースコード

post.rb

ruby

1 belongs_to :user 2 has_many :spots, dependent: :destroy 3 accepts_nested_attributes_for :spots 4 mount_uploader :image, ImageUploader

spot.rb

ruby

1 belongs_to :post 2 mount_uploader :image, ImageUploader 3 4 validates :title, length: {maximum: 30} 5 #validates :post_id, presence:true 6 validates :content, presence:true, length: { maximum: 140 } 7 validate :image_size 8 9 #住所を変換して、緯度をlattude、経度をlongitudeに保存 10 geocoded_by :address 11 after_validation :geocode

posts_controller.rb

ruby

1def new 2 @post = Post.new 3 @post.spots.build 4 end 5 6def create 7 @post = current_user.posts.build(post_params) 8 @post.save 9 redirect_to root_path 10 end 11 12def post_params 13 params.require(:post).permit(:content, spots_attributes: [:address, :image, :content, :title]) 14 end

posts/new.html.erb

html

1<div class="container"> 2 <h1 class="form-heading">投稿する</h1> 3 <%= form_with model: @post do |f|%> 4 <div class="field"> 5 <%= f.text_area :content, placeholder: "post.content"%><br> 6 <div id="forms"> 7 <div class="spot-form"> 8 <%= f.fields_for :spots do |s| %> 9 <%= s.text_field :title, placeholder: "title"%><br> 10 <%= s.text_field :address, placeholder: "address"%><br> 11 <%= s.text_area :content, placeholder: "spot.content"%> 12 <span class="image"> 13 <%= s.file_field :image, accept: 'image/jpeg,image/gif,image/png' %> 14 </span><br> 15 <% end %> 16 </div> 17 </div> 18 </div> 19 <div class="btn btn-primary" id="add-form">フォームを追加</div> 20 <%= f.submit "投稿", class: "btn btn-primary" %> 21 22 <% end %> 23 24</div> 25 26<!-- フォームの追加 --> 27<script> 28$(function(){ 29 $('#add-form').on('click',function(){ 30 var clone = $('#forms .spot-form:first').clone(true); 31 clone.appendTo('#forms') 32 }); 33}); 34</script>

spotsテーブル

ruby

1t.string :title 2t.text :content 3t.string :image 4t.string :address 5t.float :latitude 6t.float :longitude 7t.references :post, foreign_key: true 8t.timestamps

postテーブル

ruby

1t.text :content 2t.references :user, foreign_key: true

試したこと

jQueryや素のJavaScriptなどを使わず、fields_for部分をコピペして、最初からフォームが複数用意された状態にすると、すべてのフォームのデータが保存されました。

補足

postとspotで紛らわしくてすみません…
もし分かりづらい点や、不足情報があればご指摘ください

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

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

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

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

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

guest

回答1

0

ベストアンサー

以前のコメントにも書きましたがcocoonを使うと簡単に実装できると思います。
https://qiita.com/hitochan/items/5a45a95e644492d66160


せっかくなので。。。
今後のためにも下記のような方法で「何が起こっているか」を確認するとよいかと思います。

アプローチ① 〜コードの比較〜

「最初からフォームが複数用意された状態」で、Chromeの右クリック⇒ページのソースを表示してから、https://difff.jp/に貼り付ける。
次に「jQueryで同じ数のフォームを追加したとき」のソースを上記に貼り付けて、比較してみる。

⇒これで理由がわかると思いますが・・・


アプローチ② 〜コードの比較〜

フォームからどのような値が送られているかデバッグしてみる。
質問からデバッグしたような記述がみられないため、もしやり方を知らなければ一度学んでおいたほうが良いかと思います。

参考:デバッグのやり方

投稿2020/11/16 01:35

no1knows

総合スコア3365

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

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

no1knows

2020/11/16 01:37

Turbolinksを利用している場合、フォームにjQueryを直接記載していると、期待通りの動きにならない可能性が考えられます。 application.jsにTurbolinksを考慮しつつ記載したほうが好ましいかと思います。
退会済みユーザー

退会済みユーザー

2020/11/16 11:46

cocoonの「複数のデータを同時保存」というのを誤って解釈していて、このケースでは適用できないんじゃないかと思っていましたが、改めて調べてみたところ思い通りのことができそうですね。 お手数をおかけしました。再度ご回答頂きありがとうございます。 デバッグに関しても知識がほとんどないような状態ですので、一度学んでおこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問