Rails中使用remote: true提交表单时JSON.parse语法错误求助
看起来你遇到的核心问题是:浏览器把控制器返回的JavaScript代码当成JSON来解析了,这是因为remote: true默认会让AJAX请求期望application/json类型的响应,而你的控制器返回的是JS,导致解析失败。下面是具体的排查和解决步骤:
1. 显式指定AJAX请求的响应类型
修改你的form_for代码,添加data: { type: 'script' },告诉Rails这个异步请求期望接收JavaScript响应,而不是默认的JSON:
= form_for Message.new, remote: true, data: { type: 'script' } do |f| = hidden_field_tag :authenticity_token, form_authenticity_token = f.text_field :name, placeholder: 'Naam' = f.text_field :email, placeholder: 'E-mail' = f.text_area :message, placeholder: 'Jouw bericht' = f.submit #flash-message
原来的format: :js只是给URL添加了.js后缀,但并没有改变AJAX请求的Accept头,所以浏览器还是会尝试解析成JSON。加上data-type: 'script'后,请求的Accept头会变成text/javascript,控制器返回的JS就会被正确执行。
2. 优化控制器的参数处理与响应逻辑
你的控制器代码里已经有format.js分支,但注意Rails 4及以上版本需要强参数,当前的params[:message]可能会导致参数不允许的问题,建议补充强参数方法,同时确保响应逻辑清晰:
def create @message = Message.new(message_params) # 使用强参数 respond_to do |format| if @message.valid? # MessageMailer.contact(@message).deliver format.html format.js { flash.now[:success] = "Thank you for your message. I'll get back to you soon!" } else format.html format.js { flash.now[:failure] = "Something went wrong!" } end end end private def message_params params.require(:message).permit(:name, :email, :message) end
3. 确认flash部分的渲染正确性
确保你的_flash.html.erb部分能正确渲染flash消息,比如:
<% if flash[:success] %> <div class="alert alert-success"><%= flash[:success] %></div> <% elsif flash[:failure] %> <div class="alert alert-danger"><%= flash[:failure] %></div> <% end %>
同时create.js.erb里的j render 'flash'已经用escape_javascript(别名j)正确转义了HTML内容,避免出现JS语法错误。
错误原因复盘
remote: true默认依赖jquery-ujs处理AJAX请求,它默认的dataType是json,所以浏览器会把服务器返回的任何内容都尝试解析成JSON。当你的控制器返回JS代码时,JSON解析器自然会报错——因为JS不是有效的JSON格式。通过指定data: { type: 'script' },我们告诉jquery-ujs期望接收脚本类型的响应,它就会直接执行返回的JS,而不是解析成JSON。
内容的提问来源于stack exchange,提问作者Danny

