Form_with не попадает в действие контроллера

Я пробовал и form_tag, и form_with - результат тот же, действие контроллера никогда не срабатывает.

# routes.rb
resources :products do
  member do
    patch :add_comment
  end
end

# products_controller.rb
def add_comment
  # !!! damn form_with never gets here!!!
  product.add_comment!(params[:comment_id])
  redirect_back(fallback_location: products_path)
end

# view
<%= form_with(url: add_comment_product_path, local: true) do |form| %>
  <%= form.text_field :comment_id %>
  <%= form.submit 'Add comment' %>
<% end %>

Актуальные журналы:

Started PATCH "/products/1"
Processing by ProductsController#update as HTML
Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"token",
  "products"=>{a_lot: :of_stuff},
  "comment_id"=>"2",
  "commit"=>"Add comment",
  "id"=>"1"
}

Ожидаемые журналы:

Started PATCH "/products/1/add_comment?comment_id=2"
Processing by ProductsController#add_comment as HTML
Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"token",
  "comment_id"=>"2",
  "id"=>"1"
}

Редактировать:

Я думаю, это как-то связано с тем фактом, что этот form_with вложен в более крупную форму, и, похоже, когда я нажимаю Add comment, он запускает внешнюю отправку.

В исходном комментарии запрашивались маршруты, и я просто увидел его тогда. Комментарий - это отдельный ресурс или в записи продукта есть comment_id?

BenKoshy 05.10.2018 17:50

@BKSpurgeon, я думаю, это не имеет значения, дело в том, что я не могу выполнить действие контроллера с помощью form_tag или form_with. «Comment» - это отдельная модель, но вопрос содержит очень упрощенную форму того, над чем я работаю (надеюсь, это очевидно). Основная цель - заставить form_with вызывать правильное действие контроллера.

Andrey Deineko 05.10.2018 17:53

Где определяется form? Вы вроде не передаете его блоку (т.е. form_with ... do |form|)

AbM 05.10.2018 17:57

@AbM хороший улов, это опечатка. Отредактировано

Andrey Deineko 05.10.2018 17:58

Что на выходе rake routes | grep add_comment_product? Кроме того, вы должны передать идентификатор продукта в URL-адрес, то есть add_comment_product_path(some_id)? Это приведет к созданию /products/1/add_comment, а не /products/1/add_comment?comment_id=2, поскольку вы не передаете comment_id по URL-адресу.

AbM 05.10.2018 18:01

Следует отметить, что стандарты HTML (как HTML5, так и более старые (x) HTML-стандарты) не допускают вложенных элементов <form>, и поведение может быть очень непредсказуемым, поскольку не указано, должен ли браузер использовать атрибут действия вложенной формы или переместите событие в родительский элемент формы, что, скорее всего, происходит в вашем случае. w3.org/TR/html5/forms.html

max 05.10.2018 18:37

@AndreyDeineko, я спрашиваю, потому что в противном случае это вложенный ресурс, как указано в максе (см. Ответ макс ниже)

BenKoshy 06.10.2018 10:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
7
2 499
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Эй, попробуй это -

# products_controller.rb
def add_comment
  # You need add permitted for get parameters
  params.permit(:comment_id)
  product.add_comment!(params[:comment_id])
  redirect_back(fallback_location: products_path)
end

# You can place this form anywhere in your application, but you need to specify product object and comment_id
<%- @product = Product.find(1) %>
<%= form_with(url: add_comment_product_path(@product, comment_id: 2), local: true, method: :patch) do |form| %>
  <%= form.text_field :comment_id %>
  <%= form.submit 'Add comment' %>
<% end %>

Started PATCH "/products/1/add_comment?comment_id=2" for 127.0.0.1 at 2018-10-05 22:01:37 +0600
Processing by ProductsController#add_comment as HTML

Parameters: {"utf8"=>"✓", "authenticity_token"=>"token", "comment_id"=>"2", "commit"=>"Add comment", "id"=>"1"}

пожалуйста, удали свой ответ. Это копировать вставить моего кода.

Andrey Deineko 05.10.2018 18:07

Пожалуйста, внимательно сравните со своим вопросом.

Sahidur Rahman Suman 05.10.2018 18:09

Я также был проверен, если вы не укажете метод, то по умолчанию это метод POST, вот мой журнал тестового приложения - Запущен POST "/ products / 2 / add_comment" для 127.0.0.1 в 2018-10-05 22:17:31 + 0600, ActionController :: RoutingError (Нет маршрута, соответствующего [POST] "/ products / 2 / add_comment")

Sahidur Rahman Suman 05.10.2018 18:19
add_comment_product PATCH  /products/:id/add_comment(.:format)    products#add_comment

Вы объявили его как маршрут член, но я не вижу, что вы передаете какое-либо значение для :id помощника пути.

Попробуйте изменить его на

<%= form_with(url: add_comment_product_path(product), local: true) do |form| %>

где product - это экземпляр Product.

к сожалению, не имеет значения

Andrey Deineko 05.10.2018 18:13

@AndreyDeineko Это работает <%= form_with(model: @your_product_instance, url: add_comment_product_path, local: true) do |form| %>?

Pavan 05.10.2018 18:34
add_comment_product_path(product) фактически создаст правильный маршрут. Я считаю, что проблема в том, что вызов <%= form_with %> вложен в другую форму, которая создает недопустимый HTML.
max 05.10.2018 19:55

Rails справится с этим как с отдельным, но вложенным ресурсом - поскольку вы действительно создаете новый ресурс (комментарий), а не изменяете сам продукт.

Это также поддерживает ваш код в соответствии с принципом единой ответственности (SRP), поскольку каждый контроллер обрабатывает CRUD только для одного типа ресурса.

Вы можете ресурсы гнезда, вложив вызовы в resources:

resources :products do
  resources :comments, shallow: true
end

Затем настройте CommentsController для обработки комментариев CRUD:

class CommentsController < ApplicationController
  before_action :set_comment, only: [:index, :new, :create]

  # GET /products/:product_id/comments
  def index
    @comments = @product.comments
  end

  # GET /products/:product_id/comments/new
  def new
    @comment = @product.comments.new
  end

  # POST /products/:product_id/comments
  def create
    @comment = @product.comments.new(comment_params)
    if @comment.save
      redirect_to @product, success: 'Comment created'
    else
      render :new
    end
  end

  # ...

  private
  def set_product
    @product = Product.find(params[:product_id])
  end

  def comment_params
    params.require(:comment)
          .permit(:foo, :bar)
  end
end

Чтобы установить атрибут действия формы так, чтобы он указывал на вложенный маршрут, вы просто используете массив или именованный помощник маршрута product_comments(product_id: @product.to_param).

<%= form_with(model: @comment, url: [@comment.product, @comment], local: true) do |form| %>
  <%= form.submit 'Add comment' %>
<% end %>

Поскольку идентификатор продукта передается через URI, нет необходимости передавать его через скрытый ввод.

I think it has something to do with the fact that this form_with is nested into bigger form and it looks when I hit Add comment it triggers the outer submit

Следует отметить, что стандарты HTML (как HTML5, так и более старые (x) стандарты HTML) не допускают вложенных элементов формы, и поведение может быть очень непредсказуемым, поскольку не указано, должен ли браузер использовать атрибут действия вложенной формы или пузырек в родительский элемент формы, что, скорее всего, происходит в вашем случае. см .: http://w3.org/TR/html5/forms.html

Вы можете опустить действие index и new, если форма и отображение комментариев находятся на /products/:id.

max 05.10.2018 18:27

Я понял это после того, как поставил под сомнение редакцию. Я скоро протестирую вложенный ресурс, но я уверен, что это правильный путь. Маан, я не работал над представлениями уже несколько лет, просто тяжелые бэкэнд-штуки, совершенно забыл, как это просто. Спасибо за ответ, я дам вам знать, как все прошло, как только попробовал

Andrey Deineko 05.10.2018 18:36

Надеюсь, вы видели мой комментарий о том, что вложенные элементы <form> не разрешены в стандартах HTML - это объясняет, почему форма не отправляется по ожидаемому маршруту.

max 05.10.2018 19:52
Ответ принят как подходящий

Мне просто пришлось переместить вложенную форму из большей формы, чтобы она заработала.

Другие вопросы по теме