Как предотвратить появление нескольких форм simple_fields_for? - PullRequest
0 голосов
/ 27 июня 2018

У меня есть форма simple_fields_for, которая отображается внутри итератора, например:

<%= simple_form_for @port_stock, url: port_stocks_sell_order_path, method: :post, html: { class: "form-inline" } do |f| %>

  <% @buy_port_stocks.each do |port_stock| %>
    <%= f.simple_fields_for :closed_positions, html: { class: "form-inline" } do |c| %>
      <div class="form-group">
        <%= c.input_field :port_stock_id, as: :hidden, value: port_stock.id %>
        <%= c.input_field :num_units, id: "sell-ps-#{port_stock.id}", placeholder: "Number of Units", class: "form-control mx-sm-3" %>
         <%= c.input_field :closed_price, id: "sale-price-for-ps-#{port_stock.id}", placeholder: "Sale Price", class: "form-control mx-sm-3" %>
       </div>
   <% end %>
  <% end %>
<% end %>

В моем контроллере у меня есть это:

@port_stock = current_user.port_stocks.friendly.find(params[:id])
@buy_port_stocks = current_user.port_stocks.buy.joins(:stock).where(stocks: { ticker: @stock.ticker})
@cp = @port_stock.closed_positions.build

Моя PortStock.rb модель:

  has_many :closed_positions, dependent: :destroy
  accepts_nested_attributes_for :closed_positions, allow_destroy: true

Моя ClosedPosition.rb модель:

class ClosedPosition < ApplicationRecord
  belongs_to :closer, class_name: "PortStock", foreign_key: "closer_id"
  belongs_to :closed, class_name: "PortStock", foreign_key: "port_stock_id" 
end

Вышеописанное прекрасно работает для @port_stock записей, которые не имеют closed_positions.

Например, эта форма отображается так:

good-rendering-of-simple_form_for

Обратите внимание, что поля Number of Units и Sale Price отображаются только один раз в каждой строке (что я и ожидаю).

Однако, когда я создаю closed_position на любом PortStock, это создает две проблемы:

Первый выпуск

Он предварительно заполняет существующую закрытую позицию как поле, а затем отображает другое пустое поле для closed_positions, то есть так:

first-issue

Я хочу, чтобы она просто отображала новую форму, а не повторно отображала существующие значения closed_position в каждой строке. Пользователь не должен иметь возможности редактировать существующие закрытые позиции в этой форме.

Второй выпуск

При наличии нескольких закрытых позиций в каждом ряду отображаются неправильные.

wrong-values-rendered-for-each-closed-position

Обратите внимание, как каждое отображаемое значение говорит num_units: 100 && price: 8.0, посмотрите на вывод консоли тех же закрытых_позиций:

=> [#<ClosedPosition:0x00007ff13e77c6d0
  id: 9,
  closer_id: 2,
  port_stock_id: 17,
  num_units: 100,
  closed_price: 8.0,
  ticker: "CAC",
 #<ClosedPosition:0x00007ff13e77c2e8
  id: 10,
  closer_id: 3,
  port_stock_id: 18,
  num_units: 10,
  closed_price: 7.95,
  ticker: "CAC",
 #<ClosedPosition:0x00007ff13e77c018
  id: 11,
  closer_id: 10,
  port_stock_id: 19,
  num_units: 50,
  closed_price: 7.9,
  ticker: "CAC",

На самом деле правильные значения:

  1. Количество шт .: 100 && Цена: 8.0
  2. Количество единиц: 10 && Цена: 7,95
  3. Количество единиц: 50 && Цена: 7,9

Я не понимаю, почему он выводит одинаковое значение для всех port_stock объектов.

Как мне исправить эти две проблемы в моей simple_fields_for форме?

1 Ответ

0 голосов
/ 27 июня 2018

ОК, позвольте мне обучить этому с моей неубедительной логикой, но я основываюсь на ActionView :: Helpers :: FormHelper

Независимо от simple_form или стандартных помощников Rails, существует разница между передачей связанной записи и связанной модели.

<%= form_for @record %>
  <%= fields_for @associated_record %>

против

<%= form_for @record %>
  <%= fields_for :associated_model %>

И я считаю, что это связано с созданием новой записи, когда ее нет.

Итак, мое первое колебание в комментариях состояло в том, чтобы предложить использовать более конкретную переменную записи:

: закрытые_позиции @ cp

Вроде так:

<%= simple_form_for @port_stock, url: port_stocks_sell_order_path, method: :post, html: { class: "form-inline" } do |f| %>
  <% @buy_port_stocks.each do |port_stock| %>
    <%= f.simple_fields_for @cp, html: { class: "form-inline" } do |c| %>
      ...

Как вы прокомментировали, это не идеальное решение, но оно решает повторяющиеся поля.

Но, как показывает ваш контроллер, @cp не является прямой связью с @buy_port_stocks, через которую проходит форма.

Итак, решение, которое вы действительно обнаружили, состоит в том, чтобы объявить и то, и другое:

Поля могут отражать объект модели двумя способами - как они называются (следовательно, как представленные значения отображаются в хэше params в контроллере) и какие значения по умолчанию отображаются при первом отображении формы, в которой отображаются поля. Чтобы обе эти функции были указаны независимо, как имя объекта (представленное символом или строкой), так и сам объект могут быть переданы методу отдельно

И документы предлагают объявить оба, что в вашем случае выглядело бы так:

<%= simple_form_for @port_stock, url: port_stocks_sell_order_path, method: :post, html: { class: "form-inline" } do |f| %>
  <% @buy_port_stocks.each do |port_stock| %>
    <%= f.simple_fields_for :closed_positions, @cp, html: { class: "form-inline" } do |c| %>
      ...

Хотя я, очевидно, возьму богатство и славу, связанные с правильным ответом, справедливо признать, что я не привел вас туда одного.

...