简体   繁体   English

JSON模板

[英]JSON Templating

As a bit of background, I'm in the early design phases of a large RoR project for the company I work for and we're planning on sticking with Rails for the next 5-10 years. 作为一个背景,我正处于我工作的公司的大型RoR项目的早期设计阶段,我们计划在未来5到10年内坚持使用Rails。 We're at this point in the project we're trying to get some good practices and customize the framework to work for what we're going to be needing need. 我们正处于项目的这一阶段,我们正在尝试获得一些好的实践并定制框架以满足我们需要的需求。 We've considered the pros/cons of going with a full blown web-app (Backbone.js style) vs. a static limited JS based Rails app. 我们考虑了使用完整的Web应用程序(Backbone.js样式)与静态有限的基于JS的Rails应用程序的优缺点。 While we would have loved to go with a webapp, I've determined that going with Backbone.js would cause: 虽然我们本来喜欢使用webapp,但我已经确定使用Backbone.js会导致:

  • Complete duplication of views and routes (a maintenance issue in the long run) 完整的视图和路径重复(从长远来看是一个维护问题)
  • Difficulty tracking polymorphic associations and their routes 难以跟踪多态关联及其路由
  • Wouldn't allow us to use the view helpers on the client side (maintenance issue) 不允许我们在客户端使用视图助手(维护问题)
  • Duplication of some of the model information 复制一些模型信息
  • Slow client-end computers (beyond our control), which would have difficulty running it 客户端计算机速度慢(超出我们的控制范围),运行起来很困难

To try and reduce this, we're decided to go with a more hybrid approach but to push more of the logic back to the server side while still maintaining a RESTFUL architecture as an API as best as possible. 为了尝试减少这种情况,我们决定采用更加混合的方法,但是将更多的逻辑推回到服务器端,同时尽可能地将RESTFUL架构作为API维护。 We're planning on having the initial page loads done normally using Rails, and then any manipulations on the page send the request via AJAX and receiving back a JSON object which contains the rendered partial, and some additional information (ie. flash updates, JSON representation of the object, additional JS includes if necessary, etc.) 我们计划使用Rails正常完成初始页面加载,然后页面上的任何操作都通过AJAX发送请求并接收包含渲染部分的JSON对象,以及一些其他信息(即闪存更新,JSON)对象的表示,如果需要,还包括其他JS等)

The problem we're running into, is that from my understanding, we cannot maintain the RESTFUL architecture and have multiple partials/views for that same data. 我们遇到的问题是,根据我的理解,我们无法维护RESTFUL架构并且具有针对相同数据的多个部分/视图。 As an example of this, if I wanted to request a list of Orders from the server via orders/index, it would return only one view of the data. 作为一个例子,如果我想通过订单/索引从服务器请求订单列表,它将只返回一个数据视图。 If I had an extended table, a list, or some other view/partial/widget which I wanted the requested partial to be used for. 如果我有一个扩展表,一个列表或一些其他视图/部分/小部件,我希望所请求的部分用于。

To that end, I've added a params[:partial] (which is either an add-on on the route, or a url parameter) that provides the server both with the information that is being requested, as well as the view which I am expecting it to come in. This would work well on it's own, however I'd also like to have any additional information sent down from the server at the same time (ie. flash updates, JSON representation of the data, etc.). 为此,我添加了一个params [:partial](它是路由上的附加组件,或者是url参数),它为服务器提供了所请求的信息,以及视图我希望它能够进入。这本身就可以很好地工作,但是我也希望同时从服务器发送任何其他信息(即闪存更新,数据的JSON表示等)。 )。 Ideally we want this to be flexible, fast, and sent down from the server in JSON format. 理想情况下,我们希望它灵活,快速,并以JSON格式从服务器发送。

To that end, I've overriden the existing JSON responder as follows, and you may notice the hack I've had to use to have it render the HAML/ERB templates inside of the JSON: 为此,我已经覆盖了现有的JSON响应器,如下所示,您可能会注意到我必须使用它来渲染JSON中的HAML / ERB模板:

module ExtraFunctions
 def partial_options
   params.include?(:partial) ? { :partial => params[:partial] } : {}
 end

 def flash_options
   { :file => 'layouts/_flash.html.haml' }
 end
end

ApplicationController.send :include, ExtraFunctions

#I would love to be using the ERB templating and views
#instead of this kludge.  But this will have to do.

ActionController::Renderers.add :json do |json, options|

 #Change the format so we can render the html templates
 self.formats = [:html]
 options = { :layout => false }

 partial_opt = options.merge(self.respond_to?(:partial_options) ? self.partial_options : {})
 flash_opt   = options.merge(self.respond_to?(:flash_options) ? self.flash_options : {})

 obj = {
   json: json.as_json,
   partial: render_to_string(partial_opt),
   flash: flash,
   flash_partial: render_to_string(flash_opt),
   user: @current_user
   #js-includes: #Working on this
 }


 #Change the format back
 self.formats = [:json]

 json = obj.to_json(options) unless obj.kind_of?(String)
 json = "#{options[:callback]}(#{json})" unless options[:callback].blank?

 self.content_type ||= Mime::JSON
 json
end

You'll notice there is a spot in there for js-includes, the reason for that is that I want the ability to have dynamic includes late in the game using head.js. 您会注意到js-includes中有一个位置,原因是我希望能够使用head.js在游戏后期使用动态包含。 This would be for easier dependency management, as the initial view would not be including some of the partials that are requested via AJAX (ie. if I grabbed a form to enter a new address, and that form has some AJAX checking on it as included in the top of it using a content_for tag). 这将是更容易的依赖管理,因为初始视图不会包括通过AJAX请求的一些部分(即,如果我抓住一个表单来输入新地址,并且该表单对其进行了一些AJAX检查,包括在其顶部使用content_for标记)。 Ideally, what I'd really like this to be is a JSON layout to look something like (though with a more sugar coated syntax I would hope): 理想情况下,我真正喜欢的是JSON布局看起来像(虽然我希望有更多的糖涂层语法):

** json/application.json.erb **
{
   json: <%= json.as_json %>,
   partial: <%= render_to_string(partial_opt) %>,
   flash: <%= flash %>,
   flash_partial: <%= render_to_string(flash_opt) %>,
   user: <%= @current_user =>,
   js-includes: <%= yield :js_includes %>,
   <%= yield =>
}

I've been working on these considerations/issues for a while, and my questions are two: 我一直在研究这些考虑/问题,我的问题是两个:

1) Is there anything blatantly screamingly stupid about what we're doing? 1)对于我们正在做的事情,有什么明显的蠢事吗? Is there a better or more standard solution? 有更好或更标准的解决方案吗?

2) Is there a way to have ERB render the templates for JSON? 2)有没有办法让ERB渲染JSON的模板?

Thanks! 谢谢!

Bottom line, this is a common problem that there isn't yet a strong opinion on solving. 最重要的是,这是一个普遍的问题,对解决方案还没有强烈的意见。

David Heinemeier Hansson talked about this problem a bit at RailsConf 2011 when he introduced the new Asset Pipeline in Rails 3.1, noting that they've started using what they call pjax to handle refreshing parts of a page and suggested it'd be part of Rails in time. David Heinemeier Hansson在RailsConf 2011中谈到了这个问题,他在Rails 3.1中引入了新的Asset Pipeline,并指出他们已经开始使用他们所谓的pjax来处理页面的刷新部分并建议它是Rails的一部分及时。

37signals has also built Cinco (all-js mobile-app framework) and was planning on open sourcing it, but I believe they've started growing away from some of the ideas they were building it with, so I don't know what the status is. 37signals还建立了Cinco(all-js移动应用程序框架),并计划开源,但我相信他们已经开始逐渐远离他们正在构建它的一些想法,所以我不知道是什么地位是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM