форма по умолчанию НЕ удалена и не ожидает ответа через JS

#ruby-on-rails

Вопрос:

Класс shop

   accepts_nested_attributes_for :shopzones, allow_destroy: true
 

в то время как shops_controller определяет действие и пытается определить сильные параметры

 def shopzone
  @shopzone = Shopzone.new
  @shopzone.save
end

def shopzone_params  # in addition to the def shop_params method
  params.require(:shopzone).permit(:shop_id, :name, :sequence, :area)
end
 

Форма

  <%= form_with url: shopzone_shop_path(id: @shop.id) do |f| %>
    <%= f.hidden_field 'shopzone[shop_id]', value: @shop.id %>
    <div class='grid-x grid-padding-x'>
      <div class='cell small-3 alert'>
        <%= t('name') %>
        <%= f.text_field 'shopzone[name]' %>
        <%= t('sequence') %>:
        <%= f.number_field 'shopzone[sequence]' %>
      </div>
    </div>
    <div class='grid-x grid-padding-x'>
      <div class='cell small-12 text-center'>
        <%= f.submit t('create'), class: 'button' %>
      </div>
    </div>
  <% end %>
 

Но он отображается не data-remote="true" так, как ожидается по умолчанию.

 <form action="/shops/3/shopzone" accept-charset="UTF-8" method="post">
 

При отправке параметры регистрируются, но в соответствии с ожидаемым HTML-ответом

 Processing by ShopsController#shopzone as HTML
  Parameters: {"authenticity_token"=>"[FILTERED]", "shopzone"=>{"shop_id"=>"3", "name"=>"central", "sequence"=>"1"
 

Если форма изменена на

 <%= form_with(url: shopzone_shop_path(id: @shop.id), local: false) do |f| %>
 

затем данные удаленно отображаются

 <form action="/shops/3/shopzone" accept-charset="UTF-8" data-remote="true" method="post">
 

Однако ответ сервера по-прежнему ожидает обработки HTML

 Processing by ShopsController#shopzone as HTML
[...]
ActionController::UnknownFormat (ShopsController#shopzone is missing a template for this request format and variant.

request.formats: ["text/html"]
 

Таким образом, первая странность заключается в том, что предполагаемое поведение rails по умолчанию не срабатывает?
Если к действию controlelr добавляется

 respond_to do |format|
  format.js
end
 

Процесс выполняется

 Started POST "/shops/3/shopzone" for ::1 at 2021-06-11 10:34:28  0200
Processing by ShopsController#shopzone as JS
  Parameters: {"authenticity_token"=>"[FILTERED]", "shopzone"=>{"shop_id"=>"3", "name"=>"central", "sequence"=>"1" [...]
 

но затем жалуется на проверки, которые существуют в модели

 ActiveRecord::RecordInvalid (Validation failed: Shop must exist, Sequence can't be blank, Name can't be blank):
 

что противоречит представленным параметрам. Проверка параметров в действии перед сохранением puts @shopzone.inspect эффективно возвращает нулевые параметры.

Таким образом, что-то во вложенных атрибутах отбрасывает поведение по умолчанию.

Как лучше всего обработать запрос как ненавязчивый JS ?

Комментарии:

1. Это не похоже на правильное использование вложенных параметров. объектом вашей формы должен быть магазин, и он должен использовать fields_for для вложенной зоны магазина. В противном случае просто удалите вложенные параметры, так как на самом деле вы их не используете

2. Да, я пошел по этому пути. Однако у него был ряд проблем, и в итоге все оказалось не так просто. С парами есть прямой путь Shopzone.create! вперед. Увы, они сами по себе не являются «сильными».

3. По крайней мере, переместите эту функциональность в контроллер shopzone, тогда ему не имеет смысла проходить через магазины. ваша форма, похоже, ничего не меняет в магазине, так почему же она переходит в shops_controller? и удалите атрибуты nested_attributes, если вы пойдете по этому маршруту.

4. Нет необходимости в контроллере как таковом; попытка обработать класс только с помощью определения модели.

Ответ №1:

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

Поскольку Rails 6.1 form_with по умолчанию не является ajax, поэтому, чтобы сделать его ajax, вам необходимо передать local: false или установить параметр глобальной конфигурации ( config.action_view.form_with_generates_remote_forms ) в значение true.

Сравните форму с документацией Rails 5.2 .

:локально — По умолчанию отправленные формы являются удаленными и ненавязчивыми XHRS. Отключите удаленную отправку с помощью local: true.

С Рельсами 6.1

:локальная — По умолчанию форма отправляется через типичные HTTP-запросы. Включите удаленную и ненавязчивую отправку XHRs с помощью local: false. Удаленные формы могут быть включены по умолчанию, установив config.action_view.form_with_generates_remote_forms = true

Еще одна вещь, которую я вижу, это то, что вы ничего не делаете с параметрами shopzone, но даже если это сработает, пересмотрите то, как вы это создали, это не стандартное использование вложенных атрибутов.

 def shopzone
  @shopzone = Shopzone.new(shopzone_params) # you forgot this!
  @shopzone.save
end

def shopzone_params  # in addition to the def shop_params method
  params.require(:shopzone).permit(:shop_id, :name, :sequence, :area)
end
 

Комментарии:

1. shopzone_params необходимо было настроить для правильного выполнения действия, что объясняет нулевые параметры при их проверке.