Rails form_with提交后需刷新才显示评论,报ArgumentError错误
看起来你遇到了两个关联的问题:一是AJAX提交评论后页面依然强制刷新,二是控制器抛出了ArgumentError (too few arguments)。咱们一步步来拆解解决:
1. 先修复控制器的ArgumentError错误
这个报错的根源是comments_controller.rb的create动作里,respond_to块中的format调用缺少必要的处理逻辑。比如你可能写了类似这样的错误代码:
# 错误示例 def create @comment = Comment.new(comment_params) if @comment.save respond_to do |format| format.html format.js end end end
format.html和format.js后面没有指定具体的执行动作(比如重定向或渲染模板),就会触发参数不足的错误。正确的写法应该补充完整响应逻辑:
def create # 先关联评论所属的资源(假设你的评论嵌套在Resource下) @resource = Resource.find(params[:resource_id]) @comment = @resource.comments.build(comment_params) @comment.user = current_user # 如果需要关联登录用户,可添加这行 respond_to do |format| if @comment.save # 非AJAX请求时的处理:重定向回资源页面 format.html { redirect_to @resource, notice: '评论发布成功' } # AJAX请求时自动渲染同名的create.js.erb模板 format.js else # 验证失败时,非AJAX请求返回原页面 format.html { render 'resources/show' } # AJAX请求返回错误信息 format.js { render json: @comment.errors, status: :unprocessable_entity } end end end
2. 确认form_with的AJAX配置正确
Rails 5+的form_with默认开启remote: true(即AJAX提交),但最好显式确认你的表单代码没有覆盖这个默认行为:
# app/views/resources/show.html.erb中的评论表单 <%= form_with(model: [@resource, @resource.comments.build], remote: true) do |form| %> <%# 评论内容输入框 %> <%= form.text_area :content, placeholder: '写下你的评论...', class: 'comment-input' %> <%# 提交按钮 %> <%= form.submit '发布评论', class: 'comment-submit' %> <% end %>
注意这里的模型是嵌套格式[@resource, Comment.new],需要确保你的路由是嵌套配置的:
# config/routes.rb resources :resources do resources :comments, only: [:create] end
3. 创建create.js.erb实现无刷新渲染
当AJAX请求成功后,Rails会自动执行app/views/comments/create.js.erb里的JS代码,我们在这里实现把新评论插入页面的逻辑:
# app/views/comments/create.js.erb // 把新渲染的评论追加到评论列表容器末尾 $('#comments-list').append('<%= j render @comment %>'); // 清空表单输入框 $('.comment-input').val(''); // 可选:显示成功提示 $('.comment-notice').text('评论已发布').fadeIn().delay(2000).fadeOut();
这里假设你的页面中有一个id为comments-list的容器用于展示所有评论,同时你有一个渲染单个评论的局部模板_comment.html.erb:
# app/views/comments/_comment.html.erb <div class="comment-item"> <p><strong><%= @comment.user.name %></strong></p> <p><%= @comment.content %></p> <small><%= time_ago_in_words(@comment.created_at) %> 前</small> </div>
4. 可选:处理AJAX请求失败的情况
如果评论验证失败(比如内容为空),可以在控制器的else分支指定渲染错误模板,然后创建对应的JS文件来提示用户:
# comments_controller.rb的else分支 format.js { render 'error' }
然后创建app/views/comments/error.js.erb:
$('.comment-error').text('<%= j @comment.errors.full_messages.join(', ') %>').fadeIn().delay(3000).fadeOut();
这样调整后,你的评论表单应该就能实现无刷新提交,同时ArgumentError的报错也会消失啦。
内容的提问来源于stack exchange,提问作者Simon Cooper

