JSON Templating

As a little background, I am in the early stages of designing a large RoR project for the company I work for, and we plan to stick to Rails for the next 5-10 years. We are at this point in the project, we are trying to get some good practices and set up a structure to work for what we need. We examined the pros / cons of transitioning with a full-featured web application (Backbone.js style) versus the static limited JS-based Rails application. Although we would love with webapp, I decided that with Backbone.js it would call:

  • Full duplication of views and routes (a maintenance problem in the end)
  • Difficulties in tracking polymorphic associations and their routes
  • Will not allow us to use view assistants on the client side (service problem)
  • Duplication of some model information
  • Slow client computers (out of our control) that have difficulty starting it.

To try to reduce this, we decided to go with a more hybrid approach, but for more logic, return to the server side, while still preserving the RESTFUL architecture as an API, as well as possible. We plan to perform initial page loading usually using Rails, and then any manipulations on the page are sent to request via AJAX and get back a JSON object that contains a partial part and some additional information (for example, flash updates, JSON representation of an object, additional JS includes if necessary, etc.)

The problem we are facing is that, as I understand it, we cannot support the RESTFUL architecture and have several partials / views for the same data. As an example, if I wanted to request a list of Orders from the server via orders / index, this returns only one kind of data. If I had an extended table, list, or some other kind / partial / widget that I wanted to request partially for use.

params [: partial] ( url), , , , . , (, -, JSON- ..). , , JSON.

JSON : , , HAML/ERB JSON:

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

, js-includes, , , head.js. , AJAX (.. , AJAX , , content_for). , 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 =>
}

/, :

1) - , ? ?

2) , ERB JSON?

!

+3
1

, , .

RailsConf 2011, Asset Pipeline Rails 3.1, , , pjax , Rails .

37signals Cinco (all-js mobile-app framework) , , , , , .

+1

All Articles