jQuery ajax请求不会触发来自rails控制器的JS响应?

Dav*_*ite 34 jquery ruby-on-rails ruby-on-rails-3

我有一个标准的控制器,它被设置为响应HTML,JS和JSON请求:

def picture
  @picture = Picture.new params[:picture]

  respond_to do |format|
    if @picture.save
      format.html do
        logger.debug "In the HTML responder"
        redirect_to @picture
      end
      format.json { render json: @picture, status: :created, location: @picture }
      format.js { render :nothing => true }
    else
      # you get the idea
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试使用该$.ajax函数向该控制器发送请求(我不能:remote => true在这种特定情况下使用 - 我正在尝试使ajax文件上传工作).

$.ajax({
  url: $("form#new_picture").attr("action"),
  type: "POST",
  data: formdata,
  processData: false,
  contentType: false
});
Run Code Online (Sandbox Code Playgroud)

问题是我的请求由于某种原因被视为HTML请求.如何告诉rails我想要JS响应?

顺便说一句,我在我的项目中使用了jquery_ujs,所以如果有必要,我可以访问它提供的方法.我不是很擅长JS来调整那里做我需要的东西.

nde*_*eau 52

这个解决方案对我不起作用(rails 3.1 + coffeescript).在搜索了很多之后,我找到了做这件事的好方法,我想分享:

只需将".js"添加到网址的末尾即可.很简单... ;-)

  • 伙计,你太棒了:) (2认同)

shl*_*sky 31

只需添加 dataType: 'script'

$.ajax({
  url: $("form#new_picture").attr("action"),
  type: "POST",
  data: formdata,
  processData: false,
  contentType: false,
  dataType: 'script'
});    
Run Code Online (Sandbox Code Playgroud)

  • `dataType:'script'`用于响应Rails中的`js`,`dataType:'json'`用于响应`json`. (7认同)
  • dataType:'json'NOT'脚本'为我工作 (4认同)

Dav*_*ite 6

您必须在发送ajax请求之前设置'accept'标头,以便Rails知道如何响应.

$.ajax({
  url: $("form#new_picture").attr("action"),
  type: "POST",
  data: formdata,
  processData: false,
  contentType: false,
  beforeSend: function(xhr, settings) {
    xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
  }
});
Run Code Online (Sandbox Code Playgroud)


Don*_*ato 6

让我解释一下这里发生了什么。

我经常在 HTTP 中混淆客户端发送到服务器的 Accept 标头和 Content-type 标头。Accept 标头用于告诉服务器什么内容类型(application/json、application/javascript、application/octet-stream、audio/mpeg、image/png、multipart/alternative、text/plain、text/html、text/csv 、视频/mpeg 等)他们会接受。服务器发回一个响应,其中包括 Content-Type 标头,通知客户端内容的实际内容类型。

HTTP 请求也可以指定 Content-Type,因为在表单数据中,可以有所有类型的数据,而 Content-Type 头可以通知服务器数据实际上是什么(例如 multipart/form-data)。不同的媒体类型如 multipart/form-data 被称为 MIME。

现在 jQuery.ajax() 有另一个你可以传递给它的与这个主题相关的参数:accepts、contentType、dataType。

如果您了解 Content-Type HTTP 标头,则 contentType 属性很清楚。它告诉服务器数据实际上是什么。jQuery 中的默认值是“application/x-www-form-urlencoded; charset=UTF-8”,这在大多数情况下都可以。

请记住,Accept 标头告诉服务器它将接受什么 Content-Type。但是当您阅读有关 dataType 的 jQuery 文档时,它听起来非常相似:“您期望从服务器返回的数据类型。” 那么区别是什么呢?

accepts 属性允许您更改请求中的 Accept 标头。但是通过改变 dataType 也会改变 Accept 头,所以真的没有必要改变 accept 属性;dataType 将更改 Accept 标头。dataType 的好处是 ti 允许您在可用于成功处理程序之前预处理响应。

实际上,我们需要告诉 Rails 我们将接受什么作为响应头,因此我们修改了 dataType。例如,在 Rails 中,符号 :js 和 :json 对应于 HTTP Mime 类型:

Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
Run Code Online (Sandbox Code Playgroud)

因此,如果我们想触发 respond_to 块中的 :js 选项,那么我们需要在 jQuery 中将 dataType 指定为脚本。正如其中一个答案所说明的那样,您可以这样做:

$.ajax({
  url: "users/populate_user,
  type: "POST",
  data: formdata,
  dataType: 'script'
});  
Run Code Online (Sandbox Code Playgroud)

现在看看 Request Header 看起来有多漂亮:

在此处输入图片说明

请注意如何将 dataType 指定为脚本将 Accept 标头更改为 application/javascript。还要注意 contentType 是“application/x-www-form-urlencoded; charset=UTF-8”。还记得我说过如果没有指定,这是 jQuery 将使用的默认 Content-Type 吗?这个 SO 页面中提供的另一个答案也指定了这个选项:

  contentType: false
Run Code Online (Sandbox Code Playgroud)

根据 jQuery 文档:

从 jQuery 1.6 开始,您可以传递 false 来告诉 jQuery 不要设置任何内容类型标头。

最后一点。在您的 Rails 控制器中,如果此控制器操作只会响应 :js,则您不需要指定 :js 标志。您可以简单地从控制器中省略 respond_to :

  def populate_user
    @user = User.from_names(params[:name][:value]).first
  end
Run Code Online (Sandbox Code Playgroud)

然后添加一个 users/populate_user.js.erb 文件。还要确保为发布请求设置了路由:

post 'users/populate_user', to: 'users#populate_user'
Run Code Online (Sandbox Code Playgroud)

从 SO 复制和粘贴答案时,准确了解您在项目中使用的内容也很重要。


ove*_*uka 5

添加dataType: 'script'和表格数据添加如下参数format: 'js':

$.ajax({
  url: '/manager/consumers/url',
  type: 'GET',
  dataType: 'script',
  data: {
  authenticity_token: '<%= form_authenticity_token %>',
  param_1: '1',
  param_2: '2',
  format: 'js'
  }
});
Run Code Online (Sandbox Code Playgroud)

还添加控制器以不渲染布局:

  respond_to do |format|
      format.xls 
      format.js { render :layout => false }
    end
Run Code Online (Sandbox Code Playgroud)