我正在阅读一本书,并且在关于控制器的章节中谈到渲染内容时,对于 JSON,它有一个这样的示例,但没有详细说明,所以我无法弄清楚这个示例适合的更大图景:
render :json => @projects, :include => tasks
还有一些将 JSONP 与回调函数一起使用的示例:
render :json => @record, :callback => 'updateRecordDisplay'
有人可以解释这些吗?
我正在阅读一本书,并且在关于控制器的章节中谈到渲染内容时,对于 JSON,它有一个这样的示例,但没有详细说明,所以我无法弄清楚这个示例适合的更大图景:
render :json => @projects, :include => tasks
还有一些将 JSONP 与回调函数一起使用的示例:
render :json => @record, :callback => 'updateRecordDisplay'
有人可以解释这些吗?
您通常会返回JSON,因为:
A) 您正在将部分/全部应用程序构建为单页应用程序 (SPA),并且您需要客户端 JavaScript 能够在不完全重新加载页面的情况下提取额外数据。
或者
B) 您正在构建一个第三方将使用的 API,并且您已决定使用 JSON 来序列化您的数据。
或者,可能,你正在吃你自己的狗粮并且两者都做
在这两种情况下render :json => some_data
,都会对提供的数据进行 JSON 化。第二个示例中的:callback
关键需要更多解释(见下文),但它是同一想法的另一种变体(以 JavaScript 可以轻松处理的方式返回数据。)
:callback
?JSONP(第二个示例)是一种绕过同源策略的方法,该策略是每个浏览器内置安全性的一部分。如果您有您的 API,api.yoursite.com
并且您将通过 JavaScript 为您的应用程序提供服务,services.yoursite.com
那么(默认情况下)将无法从 to 发出(XMLHttpRequest
XHR - aka ajax)请求。人们一直在绕过这个限制的方式(在跨域资源共享规范最终确定之前)是通过从服务器发送 JSON 数据,就好像它是 JavaScript 而不是 JSON 一样)。因此,而不是发回:services
api
{"name": "John", "age": 45}
服务器反而会发回:
valueOfCallbackHere({"name": "John", "age": 45})
因此,客户端 JS 应用程序可以创建一个script
指向的标记,api.yoursite.com/your/endpoint?name=John
并使用来自其他来源的数据valueOfCallbackHere
调用函数(必须在客户端 JS 中定义)。)
你到底想知道什么?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 的用户,并在我们的 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);
使用此类回调的动机通常是为了规避限制跨源资源共享 (CORS) 的浏览器保护措施。然而,JSONP 不再使用那么多了,因为存在其他更安全、更容易绕过 CORS 的技术。
例如
render :json => @projects, :include => :tasks
您声明要呈现@projects
为 JSON,并将tasks
Project 模型上的关联包含在导出的数据中。
例如
render :json => @projects, :callback => 'updateRecordDisplay'
您说您想呈现@projects
为 JSON,并将该数据包装在一个 javascript 调用中,该调用将呈现如下:
updateRecordDisplay({'projects' => []})
这允许将数据发送到父窗口并绕过跨站点伪造问题。