在控制器中渲染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=Johnscript标签,并使用该函数调用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' => []}) 

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