在控制器中渲染JSON
我正在读一本书,并在关于控制器的一章中谈论渲染的东西时,对于JSON,它有一个这样的例子,但没有详细说明,所以我不能弄清楚这个例子适合的大局:
render :json => @projects, :include => tasks
JSONP还有一些使用callback函数的例子:
render :json => @record, :callback => 'updateRecordDisplay'
有人可以解释这些吗?
您通常会返回JSON ,因为:
答)您正在将部分/全部应用程序构build为单页面应用程序(SPA),并且您需要您的客户端JavaScript能够在不完全重新加载页面的情况下获取更多数据。
要么
B)您正在构build第三方将使用的API,并且您已决定使用JSON序列化数据。
或者,你可能正在吃自己的狗粮,并且都是这样做的
在这两种情况下render :json => some_data
将JSON-ify提供的数据。 第二个示例中的:callback
键需要更多解释(参见下文),但这是另一个相同想法的变体(以JavaScript可以轻松处理的方式返回数据)。
为什么:callback
?
JSONP(第二个示例)是避开每个浏览器内置安全性的一部分的同源策略的一种方式。 如果你在api.yoursite.com
有你的API,并且你将从api.yoursite.com
上提供你的应用程序,那么你的JavaScript不会(默认情况下)能够将XMLHttpRequest
(XHR – aka ajax)请求从services
提交给api
。 人们偷偷摸摸的限制( 跨源资源共享规范定稿之前 )是通过从服务器上发送JSON数据, 就好像它是JavaScript而不是JSON一样 )。 因此,而不是发回:
{"name": "John", "age": 45}
服务器反而会发回:
valueOfCallbackHere({"name": "John", "age": 45})
因此,客户端JS应用程序可以创build一个指向api.yoursite.com/your/endpoint?name=John
的script
标签,并使用该函数调用valueOfCallbackHere
函数(这将在客户端JS中定义) 来自其他来源的数据 )。
你想知道什么? ActiveRecord具有将logging序列化成JSON的方法。 例如,打开你的rails控制台并inputModelName.all.to_json
,你会看到JSON输出。 render :json
本质上调用to_json
并将结果返回给浏览器正确的头文件。 这对于您想要返回JavaScript对象的JavaScript中的AJAX调用非常有用。 此外,您可以使用callback
选项来指定要通过JSONP调用的callback的名称。
例如,假设我们有一个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对象返回的。 callback选项只是调用与JSON对象传递的命名的JavaScript函数作为第一个也是唯一的参数。
举一个callback
选项的例子,看看下面的内容:
class UsersController < ApplicationController def show @user = User.find(params[:id]) render json: @user, callback: "testFunction" end end
现在我们可以创build一个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);
使用这种callback的动机通常是为了规避限制跨源资源共享(CORS)的浏览器保护。 JSONP不再那么用了,因为有其他的技术可以绕过更安全,更简单的CORS。
例如
render :json => @projects, :include => :tasks
您正在声明要将@projects
呈现为JSON,并将导出数据中的项目模型中的关联tasks
包括在内。
例如
render :json => @projects, :callback => 'updateRecordDisplay'
你要说的是你要把@projects
渲染成JSON,并且把这些数据封装在一个javascript调用中,
updateRecordDisplay({'projects' => []})
这样可以将数据发送到父窗口并绕过跨站点伪造问题。