无法弄清楚如何在Rails中使用remote: true获取响应JSON

1 ajax ruby-on-rails ruby-on-rails-6

更新: 我发现问题是库依赖问题。我没有jquery-rails安装 gem,因此我不需要jquery-ujs在我的应用程序中使用该库。简而言之,jquery-ujs当我只有可用的内置rails-ujs功能时,我正在使用语法:( (face-palm)。感谢所有查看、提供和回答的人。


我觉得我正在做一些相当基本的事情,但由于某种原因我无法弄清楚我做错了什么。我能够通过使用帮助程序remote: true的选项,使用 AJAX 成功异步创建记录form_fordata但是,我尝试返回的简单 JSON 结构似乎在AJAX 响应的对象中不可用。当我运行时,console.log(data)undefined进入浏览器 js 控制台。

这是我的代码的相当准确的表示:

视图中的表单:

= form_for :thing, remote: true, html: { id: 'thing' } do |f|
      = f.text_field :name
      = f.submit 'submit'
Run Code Online (Sandbox Code Playgroud)

我的控制器代码:

def create
    @thing = Thing.new(thing_params)

    if @thing.save
      render json: { message: 'Thank you' }
    else
      render json: { message: 'oh no' } 
    end
end
Run Code Online (Sandbox Code Playgroud)

我的 JavaScript/jQuery:

$(document).ready(function(){
      $('#thing').on('ajax:success', function(e, data, status, xhr) {
        console.log(data)
      }).on('ajax:error', function(e, xhr, status, error){
        console.log(error)
      });
})
Run Code Online (Sandbox Code Playgroud)

我疯狂地用谷歌搜索,但我却不知所措。但也许我忽略了一些非常简单的事情。我很感激任何建议。

max*_*max 6

Rails UJS 默认发送带有 application/javascript内容类型的远程请求。

如果您想请求 JSON,请将data-type="json"属性附加到元素:

= form_for @thing, remote: true, html: { id: 'thing' }, data: { type: "json" } do |f|
  = f.text_field :name
  = f.submit 'submit'
Run Code Online (Sandbox Code Playgroud)

还有 Turbolinks 的问题。您的代码将事件处理程序直接附加到元素:

$('#thing').on('ajax:success', function(e, data, status, xhr) {
  console.log(data)
};
Run Code Online (Sandbox Code Playgroud)

虽然这在初始页面加载时有效,但当 Turbolinks 用 Ajax 替换页面内容时,它就不起作用。相反,您需要创建一个幂等事件处理程序

$(document).on('ajax:success', '#thing', function(e, data, status, xhr) {
  console.log(data);
}).on('ajax:error', '#thing', function(e, xhr, status, error){
  console.log(error);
});
Run Code Online (Sandbox Code Playgroud)

这会将一个事件处理程序附加到文档本身,该处理程序将在 DOM 冒泡时捕获该事件。因此,您不需要将此代码包装在$(document).ready(function(){ ... });.

您还应该返回有意义的 HTTP 响应代码 - 这将确定 Rails UJS 是否触发ajax:successajax:error. 不是 JSON 消息,它是反模式。

def create
  @thing = Thing.new(thing_params)

  if @thing.save
    # Tell the client where the newly created object can be found
    head :created, location: @thing
    # or return a json representation of the object
    render json: @thing, status: :created
  else
    # just return a header 
    head :unprocessable_entity
    # or return a JSON object with the errors
    render json: { errors: @thing.errors }, status: :unprocessable_entity
  end
end
Run Code Online (Sandbox Code Playgroud)