在控制器中呈现 JSON

我正在读一本书,在一个关于控制器的章节中谈到了呈现的东西,对于 JSON,它有一个类似的例子,但是没有进入到细节,所以我不能找出这个例子适合的更大的图片:

render :json => @projects, :include => tasks

还有一些 JSONP 将其与回调函数一起使用的例子:

render :json => @record, :callback => 'updateRecordDisplay'

有人能解释一下吗?

270100 次浏览

For the instance of

render :json => @projects, :include => :tasks

您声明希望将 @projects呈现为 JSON,并在导出的数据中包含 Project 模型上的关联 tasks

例如

render :json => @projects, :callback => 'updateRecordDisplay'

您声明希望将 @projects呈现为 JSON,并将该数据包装在一个 javascript 调用中,该调用将呈现如下内容:

updateRecordDisplay({'projects' => []})

这允许将数据发送到父窗口并绕过跨站点伪造问题。

你到底想知道什么?ActiveRecord 具有将记录序列化为 JSON 的方法。例如,打开 Rails 控制台并输入 ModelName.all.to_json,您将看到 JSON 输出。render :json基本上调用 to_json并将结果返回给具有正确标头的浏览器。这对于 JavaScript 中希望返回要使用的 JavaScript 对象的 AJAX 调用非常有用。另外,可以使用 callback选项指定要通过 JSONP 调用的回调的名称。

例如,假设我们有一个看起来像这样的 User模型: {name: 'Max', email:' m@m.com'}

我们还有一个这样的控制器:

class UsersController < ApplicationController
def show
@user = User.find(params[:id])
render json: @user
end
end

现在,如果我们像这样使用 jQuery 进行 AJAX 调用:

$.ajax({
type: "GET",
url: "/users/5",
dataType: "json",
success: function(data){
alert(data.name) // Will alert Max
}
});

正如您所看到的,我们设法从 Rails 应用程序获得了 id 为5的 User,并在 JavaScript 代码中使用它,因为它被作为 JSON 对象返回。回调选项只调用用 JSON 对象作为第一个也是唯一的参数传递的名称的 JavaScript 函数。

为了给出 callback选项的一个示例,请看以下内容:

class UsersController < ApplicationController
def show
@user = User.find(params[:id])
render json: @user, callback: "testFunction"
end
end

现在我们可以创建一个 JSONP 请求,如下所示:

function testFunction(data) {
alert(data.name); // Will alert Max
};


var script = document.createElement("script");
script.src = "/users/5";


document.getElementsByTagName("head")[0].appendChild(script);

The motivation for using such a callback is typically to circumvent the browser protections that limit cross origin resource sharing (CORS). JSONP isn't used that much anymore, however, because other techniques exist for circumventing CORS that are safer and easier.

You'll normally be returning JSON either because:

A)您正在构建部分/全部应用程序作为单页应用程序(Single Page Application,SPA) ,并且您需要客户端 JavaScript 能够在不完全重新加载页面的情况下引入额外的数据。

or

B)您正在构建一个第三方将使用的 API,并且您已经决定使用 JSON 来序列化您的数据。

或者,可能,你正在吃你自己的狗粮和做 都有

在这两种情况下,render :json => some_data都将 JSON 化所提供的数据。第二个示例中的 :callback键需要进一步解释(见下文) ,但它是同一思想的另一个变体(以 JavaScript 可以轻松处理的方式返回数据)

为什么是 :callback

JSONP (第二个例子)是绕过 同一原产地政策的一种方法,同一原产地政策是每个浏览器内置安全的一部分。如果你有你的 API 在 api.yoursite.com和你将服务你的应用程序离开 services.yoursite.com你的 JavaScript 将不能(默认情况下)使 XMLHttpRequest(XHR-aka ajax)请求从 servicesapi。人们绕过这个限制(在 跨来源资源共享规格已经敲定之前)的方法是从服务器 as if it was JavaScript instead of JSON发送 JSON 数据。因此,与其退回:

{"name": "John", "age": 45}

相反,服务器会发回:

valueOfCallbackHere({"name": "John", "age": 45})

因此,客户端 JS 应用程序可以创建一个指向 api.yoursite.com/your/endpoint?name=Johnscript标记,并具有名为 来自另一个原点的数据valueOfCallbackHere函数(必须在客户端 JS 中定义)