form_with не поражает действие контроллера - PullRequest
0 голосов
/ 05 октября 2018

Я пробовал оба 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 запускает внешнюю отправку

Ответы [ 4 ]

0 голосов
/ 08 октября 2018

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

0 голосов
/ 05 октября 2018
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.

0 голосов
/ 05 октября 2018

Способ 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, нет необходимости передавать его через скрытый ввод.

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

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

0 голосов
/ 05 октября 2018

Вот попробуй -

# 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"}
...