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

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

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

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

JavaScript

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

jQuery

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

Q&A

解決済

1回答

433閲覧

【Rails6】ブラウザで取得したvalueをサーバーサイドに送りたい

izu_reco

総合スコア2

Ruby on Rails 6

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

JavaScript

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

jQuery

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

1グッド

1クリップ

投稿2022/05/10 13:33

現在、一度の投稿で複数レコードを登録する機能を実装しています。

具体的に以下機能を実現したいと考えています。
❶ 食材をカテゴリ毎(魚/肉/飲料など)に入力欄を設ける。カテゴリは、タブで変更する。
❷ 例) 魚カテゴリを選択し、入力されたレコードには、魚カテゴリのidを付与したい。
❸ カテゴリのidは、jQueryを用いて、タブがクリックされると、自動的に取得できるよう実装している。
❹ カテゴリのidは、"hidden_field"で隠し、idだけサーバーサイドに送ろうとしている。
Image from Gyazo

困りごと

上記❸❹の「カテゴリidをタブ切り替えごとに取得」して、フォームの送信と共に「サーバーサイドまで送る」ことは成功していますが、idが初めのレコードにしか反映されません

Image from Gyazo
繰り返しとなりますが、やりたいことは、食材のカテゴリに応じてidを付与したい(魚のタブから入力したのであれば、魚のカテゴリidが保存したい)のです。なぜ、初めのレコードにしか付与されないのでしょうか。お知恵をお貸しいただきたくお願いいたします。

Version

Ruby on Rails 6
jQuery 3.6.0

該当のソースコード

HTML

html

1 <div class="content-area"> 2 <%= form_with model: @form, url: box_foods_path, method: :post, local: true do |form| %> 3 <%= render 'shared/foods_error_messages', model: @form %> 4 <div class="content show"> 5 <%= render partial: 'shared/fields_for', locals:{ form: form } %> 6 </div> 7 8 <div class="content"> 9 <%= render partial: 'shared/fields_for', locals:{ form: form } %> 10 </div> 11 12 <div class="content"> 13 <%= render partial: 'shared/fields_for', locals:{ form: form } %> 14 </div> 15 16 <div class="content"> 17 <%= render partial: 'shared/fields_for', locals:{ form: form } %> 18 </div> 19 20 <div class="content"> 21 <%= render partial: 'shared/fields_for', locals:{ form: form } %> 22 </div> 23 24 <div class="sell-btn-contents"> 25 <%= form.submit "登録する" ,class:"sell-btn", id:"food-btn" %> 26 <%=link_to 'もどる', root_path, class:"back-btn" %> 27 </div> 28 <% end %> 29 </div>

render(フォーム表示部分)

Ruby

1<h2>選択されている食材カテゴリ : <i class="fa-solid fa-fish"></i>Fish </h2> 2<table class="item-table"> 3 <thead> 4 <tr class="item-tr"> 5 <th>登録</th> 6 <th>食材名</th> 7 <th>個数</th> 8 <th>購入日</th> 9 <th>消費期限</th> 10 <th>購入価格</th> 11 </tr> 12 </thead> 13 <%# TODO : フォーム追加できるようにする。https://web-tsuku.life/add-form-appendchild/ %> 14 <tbody> 15 <%= form.fields_for :foods do |f| %> 16 <tr class="item-tr"> 17 <td><%= f.check_box :availability, {}, "true", "false" %></td> 18 <td><%= f.text_field :food_title %></td> 19 <td><%= f.number_field :number_title, min: 1, max: 99 %></td> 20 <td><%= f.date_field :purchase_date %></td> 21 <td><%= f.date_field :expiry_date %></td> 22 <td><%= f.text_field :price %></td> 23 <td><%= f.hidden_field :category_id, id:"send-data" %></td> 24 </tr> 25 <% end %> 26 </tbody> 27</table>

jQuery

  • 押下されたタブに応じて、hidden_fieldのvalueを書き換えています。

Javascript

1$(function() { 2 let tabs = $(".tab"); // tabのクラスを全て取得し、変数tabsに配列で定義 3 let tab_id = 1 4 $(".tab").on("click", function() { // tabをクリックしたらイベント発火 5 $(".active").removeClass("active"); // activeクラスを消す 6 $(this).addClass("active"); // クリックした箇所にactiveクラスを追加 7 const index = tabs.index(this); // クリックした箇所がタブの何番目か判定し、定数indexとして定義 8 $(".content").removeClass("show").eq(index).addClass("show"); // showクラスを消して、contentクラスのindex番目にshowクラスを追加 9 }) 10 11 $("#tab-fish.tab").on("click", function(){ 12 // どのタブが選択されたか判断 13 tab_id = $("#tab-fish.tab").data("value"); 14 $("#send-data").val(tab_id) 15 }); 16 17 $("#tab-veg.tab").on("click", function(){ 18 // タブのIDを取得 19 tab_id = $("#tab-veg.tab").data("value"); 20 $("#send-data").val(tab_id) 21 debugger; 22 }); 23})

Foods Controller

  • こちらでnew/createアクションを定義しています。
  • Formオブジェクトを組んで、複数レコードが登録できるよう実装しています。

Ruby

1class FoodsController < ApplicationController 2 def new 3 # @form = Form::FoodCollection.new(params[:box_id]) 4 @form = Form::FoodCollection.new 5 end 6 7 def create 8 @form = Form::FoodCollection.new(food_collection_params) 9 binding.pry 10 if @form.save == true 11 redirect_to root_path, notice: "商品を登録しました" 12 else 13 render :new 14 end 15 end 16 17 def edit 18 end 19 20 def update 21 end 22 23 def show 24 end 25 26 private 27 28 def food_collection_params 29 params.require(:form_food_collection) 30 .permit(foods_attributes: [:availability, :food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id, :category_id]) 31 .merge( 32 box_id: params[:box_id] 33 ) 34 end 35end

Formオブジェクト

Ruby

1class Form::FoodCollection < Form::Base 2 FORM_COUNT = 3 3 #ここで、作成したい登録フォームの数を指定 4 attr_accessor( 5 :foods, 6 :availability, :food_title, :number_title, :purchase_date, :expiry_date, :price, :give_id, :category_id, 7 :box_id 8 ) 9 # foodsに作成したモデルが格納される 10 11 with_options presence: true do 12 validates :food_title 13 validates :number_title 14 validates :purchase_date 15 validates :expiry_date 16 validates :price 17 end 18 19 # 初期化メソッド 20 21 def initialize(attributes = {}) 22 super attributes 23 self.foods = FORM_COUNT.times.map { Food.new() } unless self.foods.present? 24 end 25 26 def foods_attributes=(attributes) 27 self.foods = attributes.map { |_, v| Food.new(v) } 28 end 29 30 def save 31 is_success = true 32 ava_count = 0 33 Food.transaction do 34 self.foods.each do |food| 35 food.valid? 36 if food.availability 37 f = Food.new(box_id: box_id) 38 food.box_id = f.box_id 39 is_success = false unless food.save 40 ava_count += 1 41 end 42 end 43 if ava_count == 0 44 is_success = false 45 end 46 raise ActiveRecord::RecordInvalid unless is_success 47 end 48 49 rescue 50 p 'error' 51 ensure 52 return is_success 53 end 54end

自分で調べたことや試したこと

仮説
fields_forを用いると、欄への記載に関わらず「生成された入力欄が全てサーバーサイドに送られる」ため、カテゴリidが希望のレコードに付与されない?
ただし、もしそうであれば、その他の入力項目も正しく保存されないはずだが、jQueryで取得したカテゴリidのみ、おかしな挙動をしている。

長文かつ分かりにくい箇所があるかと思いますが、何卒よろしくお願いします。

shinoharat👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

原因

id は、ひとつのHTMLファイル内で一意でなければいけません。
しかし、質問者さんのコードだと send-data という id を持つ要素が複数出力されてしまいます。

erb

1<%= form.fields_for :foods do |f| %> 2 ... 3 <%# ↓ fields_for 内で id を指定しているので、同じ id を持つ要素が複数出力されてしまう > 4 <td><%= f.hidden_field :category_id, id:"send-data" %></td> 5 ... 6<% end %>

同じ id の要素が複数存在するような html は想定されていないため、「category_idが初めのレコードにしか反映されない」という現象が発生しています。

解決策

id の代わりに class など重複OKな属性を利用してください。

diff

1- <td><%= f.hidden_field :category_id, id:"send-data" %></td> 2+ <td><%= f.hidden_field :category_id, class:"send-data" %></td> 3 4 --- 5 6 $("#tab-fish.tab").on("click", function(){ 7 // どのタブが選択されたか判断 8 tab_id = $("#tab-fish.tab").data("value"); 9- $("#send-data").val(tab_id) 10+ $(".send-data").val(tab_id) 11 });

投稿2022/05/13 06:36

shinoharat

総合スコア1676

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

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

izu_reco

2022/05/15 13:49

返答が遅くなり、申し訳ありません。 先ほど、ご指導いただいた内容をもとに修正したところ、カテゴリごとにidを振り分けることができました。 >> idはひとつのファイルで一意でなければならない という点、よく覚えておくようにします。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問