hiddy0329
@hiddy0329 (hiddy)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Ruby on Rails コレクションモデルを用いたフォームからの一括登録時、データが保存されません。

解決したいこと

Ruby on Railsで伝票作成アプリを作っています。
事前に送り先である「取引先」を登録できるようにするため、
コレクションモデルを用いた一括登録機能を実装中なのですが、
データベースにデータが保存されません。

発生している問題・エラー

一括登録画面に情報を入力し、一括登録ボタンを押すと、以下の画像のように、URLがおかしい状態になり、
尚且つデータベースを確認すると保存されていません。

取引先登録画面.png

↓「一括登録ボタン押下」

取引先登録後エラー画面.png
URLがおかしくなる。

↓データベース確認

データベース.png
データベースには保存されていない。

この機能に関するソースコードは以下の通り。

該当するソースコード

app/models/form/client_collection.rb

class Form::ClientCollection < Form::Base
  FORM_COUNT = 10 #ここで、作成したい登録フォームの数を指定
  attr_accessor :clients 

  def initialize(attributes = {})
    super attributes
    self.clients = FORM_COUNT.times.map { Client.new() } unless self.clients.present?
  end

  def clients_attributes=(attributes)
    self.clients = attributes.map { |_, v| Client.new(v) }
  end

  def save
    Client.transaction do
      self.clients.map do |client|
        if client.availability # ここでチェックボックスにチェックを入れている取引先のみが保存される
          client.save
        end
      end
    end
      return true
    rescue => e
      return false
  end
end

app/models/form/base.rb

class Form::Base
  include ActiveModel::Model
  include ActiveModel::Callbacks
  include ActiveModel::Validations
  include ActiveModel::Validations::Callbacks

end

app/models/client.rb

class Client < ApplicationRecord
  with_options presence: true do
    validates :name
    validates :availability, inclusion: { in: [true, false] }
  end
end

end

app/controllers/clients_controller.rb

class ClientsController < ApplicationController
  def new
    @form = Form::ClientCollection.new
  end

  def create
    @form = Form::ClientCollection.new(client_collection_params)
    unless @form.save
      render :new
    end
  end

  private

    def client_collection_params
        params.require(:form_client_collection)
        .permit(clients_attributes: [:name, :availability])
    end
end

app/views/clients/new.html.erb

<div class="container">
<form>
<%= form_for(@form, url: clients_path, method: :post) do |fb| %>
<table class="table">
<thead>
  <tr>
    <th width="80px", class="text-center h3">
    <strong>登録</strong>
    </th>
    <th class="text-center h3">
    <strong>取引先名</strong>
    </th>
  </tr>
</thead>
<tbody class="registration-form">
<%= fb.fields_for :clients do |f| %>
<tr class="item">
  <td class="text-center">
  <%= f.check_box :availability, class: 'top10 registration-checkbox' %>
  </td>
  <td>
  <%= f.text_field :name, class: 'form-control' %>
  </td>
</tr>
<% end %>
</tbody>
</table>
<div class="text-center">
<%= fb.submit '一括登録', class: 'btn btn-primary' %>
<%= link_to "戻る", root_path, class: 'btn btn-success' %>
</div>

<% end %>
</form>
</div>

自分で試したこと

この機能に関する上記のファイルを確認しましたが、問題は見当たりませんでした。
取引先登録機能以外に、商品登録機能もこれと同じように実装していますが、
そちらはしっかりと動いています。

他に見るべきポイントはないでしょうか。

0

1Answer

formタグが2重になっていそうです。

<form>
<%= form_for(@form, url: clients_path, method: :post) do |fb| %>
<table class="table">
0Like

Comments

  1. @hiddy0329

    Questioner

    @h_kono0707さん!
    アドバイスいただき、ありがとうございます!

    <form>タグを削除したらすんなりとデータを登録できました!
    フォームをフォームで囲うような二重構造になってしまったせいで、
    form_forの機能が働かなくなってしまったのでしょうか?

    自分でも調べてみます!!
  2. 結論だけ書くと2重でformタグを定義した場合、内側のタグは無視されます。
    <%= form_for(@form, url: clients_path, method: :post) do |fb| %>
    これが無視されるのでsubmitはGETとして処理されてます。
  3. @hiddy0329

    Questioner

    非常によく理解できました!
    formの入れ子構造は禁止ということですね!

    ありがとうございました!

Your answer might help someone💌