ruby-on-rails - 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
它时它看起来会触发外部提交
解决方案
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 %>
由于产品 ID 通过 URI 传递,因此无需通过隐藏输入传递它。
我认为这与这个 form_with 嵌套在更大的表单中这一事实有关,当我点击添加评论时它看起来会触发外部提交
您应该注意 HTML 标准(HTML5 和旧 (x)HTML 标准)不允许嵌套表单元素,并且如果浏览器应该使用嵌套表单的 action 属性或冒泡在您的情况下最有可能发生的父表单元素的事件。见:http ://w3.org/TR/html5/forms.html
推荐阅读
- javascript - 从javascript中的图像路径获取不带扩展名的图像名称
- yii2 - 如何解决yii2中的文件上传验证问题
- haskell - 在 Haskell 中操作元组
- java - 如何在freemarker模板中迭代对象?
- clojure - 没有为类型对象定义协议方法::empty
- powerbi - Return Slicer's Value (交易模拟器)
- javascript - 如何使用按钮在 HTML JavaScript 中不断添加文本?
- statsmodels - statsmodels ARIMA predict 给我的是差分信号的预测,而不是实际信号的预测。我犯了什么错误?
- java - 序列化复合的最佳方式 - (设计模式)
- javascript - Highcharts 上的 React 元素