Share
Embed
SpreeConf Europe: Backbone.js & Spree
A look a hypothetical Backbone.js front-end replacement for Spree Commerce, with sever-side EJS rendering.
Brian Quinn
August 23, 2012
Transcript
189 slides
-
Brian D. Quinn CTO & Co-founder Spree Commerce, Inc. github.com/bdq
twitter.com/briandq -
Overhauled Product & Order API’s Spree-API: improvements Included RABL for
response templates -
Overhauled Product & Order API’s Spree-API: improvements Included RABL for
response templates Swapped to Ransack for searching -
Overhauled Product & Order API’s Spree-API: improvements Included RABL for
response templates Swapped to Ransack for searching Improved Authentication -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 class Spree::Api::BaseController < Spree::BaseController ... respond_to :json def index respond_with(@collection) do |format| format.json { render :json => @collection.to_json(serialization_options) } end end def show respond_with(@object) do |format| format.json { render :json => @object.to_json(serialization_options) } end end ... 01. api/app/controllers/spree/api/base_controller.rb Spree-API: PRe-RABL -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 class Spree::Api::BaseController < Spree::BaseController ... respond_to :json def index respond_with(@collection) do |format| format.json { render :json => @collection.to_json(serialization_options) } end end def show respond_with(@object) do |format| format.json { render :json => @object.to_json(serialization_options) } end end ... 01. api/app/controllers/spree/api/base_controller.rb Spree-API: PRe-RABL -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 object @product attributes *product_attributes child :variants_including_master => :variants do attributes *variant_attributes child :option_values => :option_values do attributes *option_value_attributes end end child :images => :images do extends "spree/api/v1/images/show" end child :option_types => :option_types do child :option_values => :option_values do attributes *option_value_attributes end end 01. api/app/views/spree/api/v1/products/show.rabl Spree-API: With RABL -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 object @product attributes *product_attributes child :variants_including_master => :variants do attributes *variant_attributes child :option_values => :option_values do attributes *option_value_attributes end end child :images => :images do extends "spree/api/v1/images/show" end child :option_types => :option_types do child :option_values => :option_values do attributes *option_value_attributes end end 01. api/app/views/spree/api/v1/products/show.rabl Spree-API: With RABL -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 object @product attributes *product_attributes child :variants_including_master => :variants do attributes *variant_attributes child :option_values => :option_values do attributes *option_value_attributes end end child :images => :images do extends "spree/api/v1/images/show" end child :option_types => :option_types do child :option_values => :option_values do attributes *option_value_attributes end end 01. api/app/views/spree/api/v1/products/show.rabl Spree-API: With RABL -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 object @product attributes *product_attributes child :variants_including_master => :variants do attributes *variant_attributes child :option_values => :option_values do attributes *option_value_attributes end end child :images => :images do extends "spree/api/v1/images/show" end child :option_types => :option_types do child :option_values => :option_values do attributes *option_value_attributes end end 01. api/app/views/spree/api/v1/products/show.rabl Spree-API: With RABL -
Better control over JSON output Spree-API: Rabl Benefits Easily extendable
by extensions / applications -
Better control over JSON output Spree-API: Rabl Benefits Easily extendable
by extensions / applications Supports lots of formats -
Better control over JSON output Spree-API: Rabl Benefits Easily extendable
by extensions / applications Supports lots of formats Great caching support -
GET api/products/search?q[name_cont]=ruby Spree-API: RANSACK GET api/products/search?q[master_price_lteq]=10.00 GET api/orders/search?q=[email_matches]=brian%25 GET api/orders/search?q=[completed_at_present]=1
GET api/products/search?q[name_start]=Ruby GET api/products/search?q[taxons_id_eq]=12345 -
GET api/products/search?q[name_cont]=ruby Spree-API: RANSACK GET api/products/search?q[master_price_lteq]=10.00 GET api/orders/search?q=[email_matches]=brian%25 GET api/orders/search?q=[completed_at_present]=1
GET api/products/search?q[name_start]=Ruby GET api/products/search?q[taxons_id_eq]=12345 GET api/products/search?q[variants_count_on_hand_gt]=5 -
Target High traffic Pages Products Index Products Show Taxon Show
Order Edit Checkout Log In/Out -
Target High traffic Pages Products Index Products Show Taxon Show
Order Edit Checkout Log In/Out -
app/assets/javascripts/store The BASICS: Structure /models /collections /routers /views /products /templates
/taxons /products /taxons /orders /orders -
The BASICS: MODELS Product Variant Image Option Type Option Value
Taxonomy Taxon Order -
The BASICS: MODELS Product Variant Image Option Type Option Value
Taxonomy Taxon Order LineItem -
The BASICS: MODELS Product Variant Image Option Type Option Value
Taxonomy Taxon Order LineItem Adjustment -
The BASICS: MODELS Product Variant Image Option Type Option Value
Taxonomy Taxon Order LineItem Adjustment Status -
01 02 03 04 05 06 07 08 09 10
11 12 Spree.Models.Product = Backbone.Model.extend({ initialize: function(){ this.build_associations(); }, build_associations: function(){ this.images = new Spree.Collections.Images( this.get('images' ) ); ... }, ... }); 01. app/assets/javascripts/store/models/product.js The Basics: Models -
01 02 03 04 05 06 07 08 09 10
11 12 Spree.Models.Product = Backbone.Model.extend({ initialize: function(){ this.build_associations(); }, build_associations: function(){ this.images = new Spree.Collections.Images( this.get('images' ) ); ... }, ... }); 01. app/assets/javascripts/store/models/product.js The Basics: Models -
01 02 03 04 05 06 07 08 09 10
11 12 Spree.Models.Product = Backbone.Model.extend({ initialize: function(){ this.build_associations(); }, build_associations: function(){ this.images = new Spree.Collections.Images( this.get('images' ) ); ... }, ... }); 01. app/assets/javascripts/store/models/product.js The Basics: Models -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 { id: 723959550, name: "Ruby on Rails Bag", description: "Lorem ipsum tincidunt egestas. Mauris nibh...", price: "22.99", available_on: "2012-06-05T13:02:05Z", permalink: "ruby-on-rails-bag", count_on_hand: 45, images: [{ id: 3, position: 1, attachment_content_type: "image/jpeg", attachment_file_name: "ror_bag.jpeg", alt: null, viewable_type: "Spree::Variant", viewable_id: 504220342 }] } 01. Sample Products JSON Snippet The Basics: Models -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 { id: 723959550, name: "Ruby on Rails Bag", description: "Lorem ipsum tincidunt egestas. Mauris nibh...", price: "22.99", available_on: "2012-06-05T13:02:05Z", permalink: "ruby-on-rails-bag", count_on_hand: 45, images: [{ id: 3, position: 1, attachment_content_type: "image/jpeg", attachment_file_name: "ror_bag.jpeg", alt: null, viewable_type: "Spree::Variant", viewable_id: 504220342 }] } 01. Sample Products JSON Snippet The Basics: Models -
Product Variant Image Option Type Option Value Taxonomy Taxon Order
LineItem Adjustment The BASICS: Collections -
Index Show Products => Edit Orders => The BASICS: Routers
Show Taxons => -
Index Show Products => Edit Orders => Show Taxons =>
The BASICS: Views -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 //= require jquery //= require jquery_ujs //= require store/spree_core //= require store/spree_auth //= require store/spree_promo //= require jquery //= require underscore //= require backbone //= require store/spree //= require store/plumbing //= require store/paginated_collection //= require store/underscore_mixins //= require_tree ./models //= require_tree ./collections //= require_tree ./routers //= require_tree ./views //= require_tree ./templates 01. app/assets/javascripts/store/all.js The Basics: all.js -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 //= require jquery //= require jquery_ujs //= require store/spree_core //= require store/spree_auth //= require store/spree_promo //= require jquery //= require underscore //= require backbone //= require store/spree //= require store/plumbing //= require store/paginated_collection //= require store/underscore_mixins //= require_tree ./models //= require_tree ./collections //= require_tree ./routers //= require_tree ./views //= require_tree ./templates 01. app/assets/javascripts/store/all.js The Basics: all.js -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 //= require jquery //= require jquery_ujs //= require store/spree_core //= require store/spree_auth //= require store/spree_promo //= require jquery //= require underscore //= require backbone //= require store/spree //= require store/plumbing //= require store/paginated_collection //= require store/underscore_mixins //= require_tree ./models //= require_tree ./collections //= require_tree ./routers //= require_tree ./views //= require_tree ./templates 01. app/assets/javascripts/store/all.js The Basics: all.js -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 //= require jquery //= require jquery_ujs //= require store/spree_core //= require store/spree_auth //= require store/spree_promo //= require jquery //= require underscore //= require backbone //= require store/spree //= require store/plumbing //= require store/paginated_collection //= require store/underscore_mixins //= require_tree ./models //= require_tree ./collections //= require_tree ./routers //= require_tree ./views //= require_tree ./templates 01. app/assets/javascripts/store/all.js The Basics: all.js -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 //= require jquery //= require jquery_ujs //= require store/spree_core //= require store/spree_auth //= require store/spree_promo //= require jquery //= require underscore //= require backbone //= require store/spree //= require store/plumbing //= require store/paginated_collection //= require store/underscore_mixins //= require_tree ./models //= require_tree ./collections //= require_tree ./routers //= require_tree ./views //= require_tree ./templates 01. app/assets/javascripts/store/all.js The Basics: all.js -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 var Spree = { Views: { Shared: {}, Products: {}, Taxons: {} ,Orders: {} }, Routers: { _active: {} }, Models: {}, Collections: {}, Data: { _preload: {}, products: null, taxonomies: null }, current_order: null, current_user: null, init: function(){ ... } }); 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 init: function(){ if(this.Data._preload.products!=undefined){ //preload products this.Data.products = new this.Collections.Products(); this.Data.products.resetWithPagination(this.Data._preload.products); } this.Routers._active.products = new this.Routers.Products(); this.Routers._active.taxons = new this.Routers.Taxons(); this.Routers._active.orders = new this.Routers.Orders(); Backbone.history.start({pushState: true}) $('a[data-push-state]').click(this._navigate); this.status = new this.Models.Status() this.status.fetch({success: this.set_state}); } 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 init: function(){ if(this.Data._preload.products!=undefined){ //preload products this.Data.products = new this.Collections.Products(); this.Data.products.resetWithPagination(this.Data._preload.products); } this.Routers._active.products = new this.Routers.Products(); this.Routers._active.taxons = new this.Routers.Taxons(); this.Routers._active.orders = new this.Routers.Orders(); Backbone.history.start({pushState: true}) $('a[data-push-state]').click(this._navigate); this.status = new this.Models.Status() this.status.fetch({success: this.set_state}); } 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 init: function(){ if(this.Data._preload.products!=undefined){ //preload products this.Data.products = new this.Collections.Products(); this.Data.products.resetWithPagination(this.Data._preload.products); } this.Routers._active.products = new this.Routers.Products(); this.Routers._active.taxons = new this.Routers.Taxons(); this.Routers._active.orders = new this.Routers.Orders(); Backbone.history.start({pushState: true}) $('a[data-push-state]').click(this._navigate); this.status = new this.Models.Status() this.status.fetch({success: this.set_state}); } 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 init: function(){ if(this.Data._preload.products!=undefined){ //preload products this.Data.products = new this.Collections.Products(); this.Data.products.resetWithPagination(this.Data._preload.products); } this.Routers._active.products = new this.Routers.Products(); this.Routers._active.taxons = new this.Routers.Taxons(); this.Routers._active.orders = new this.Routers.Orders(); Backbone.history.start({pushState: true}) $('a[data-push-state]').click(this._navigate); this.status = new this.Models.Status() this.status.fetch({success: this.set_state}); } 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 init: function(){ if(this.Data._preload.products!=undefined){ //preload products this.Data.products = new this.Collections.Products(); this.Data.products.resetWithPagination(this.Data._preload.products); } this.Routers._active.products = new this.Routers.Products(); this.Routers._active.taxons = new this.Routers.Taxons(); this.Routers._active.orders = new this.Routers.Orders(); Backbone.history.start({pushState: true}) $('a[data-push-state]').click(this._navigate); this.status = new this.Models.Status() this.status.fetch({success: this.set_state}); } 01. app/assets/javascripts/store/spree.js The Basics: Spree Object -
The BASICS: push state /products/ruby-on-rails-mug RAILS URL: #products/ruby-on-rails-mug HASH Anchor:
/products/ruby-on-rails-mug PUSH STATE: -
The BASICS: push state /products/ruby-on-rails-mug RAILS URL: #products/ruby-on-rails-mug HASH Anchor:
/products/ruby-on-rails-mug PUSH STATE: -
01 02 03 04 _navigate: function(evt){ evt.preventDefault(); Spree.Routers._active.products.navigate($(evt.currentTarget).attr('href'), true); }
02. spree.js _navigate() function 01 02 03 04 05 init: function(){ ... $('a[data-push-state]').click(this._navigate); ... } 01. spree.js init() function The BASICS: push state -
01 02 03 04 _navigate: function(evt){ evt.preventDefault(); Spree.Routers._active.products.navigate($(evt.currentTarget).attr('href'), true); }
02. spree.js _navigate() function 01 02 03 04 05 init: function(){ ... $('a[data-push-state]').click(this._navigate); ... } 01. spree.js init() function The BASICS: push state -
01 02 03 04 _navigate: function(evt){ evt.preventDefault(); Spree.Routers._active.products.navigate($(evt.currentTarget).attr('href'), true); }
02. spree.js _navigate() function 01 02 03 04 05 init: function(){ ... $('a[data-push-state]').click(this._navigate); ... } 01. spree.js init() function The BASICS: push state -
Index Show Edit Products => Orders => The BASICS: Templates
Pagination Show Taxons => -
Index Show Edit Products => Orders => The BASICS: Templates
Pagination Cart Link Account Links Show Taxons => -
01 02 03 04 05 06 07 <td class="cart-item-image" data-hook="cart_item_image">
<% if variant.images.length == 0 %> <%= link_to small_image(variant.product), variant.product %> <% else %> <%= link_to image_tag(variant.images.first.attachment.url(:small)) ... <% end %> </td> 01. Original HTML.ERB Template 01 02 03 04 05 06 07 <td class="cart-item-image" data-hook="cart_item_image"> <% if(line_item.product.images.size()>0){ %> <a href="/products/<%= line_item.product.get('permalink') %>" <img src="/spree/products/<%= line_item.product.images.first().id %>/... </a> <% } %> </td> 02. Replacement JST.EJS Template Template: Conversion -
Scribble: REsponder Request Render Products => Index JST.EJS File Exists?
app/views/spree/products/index.jst.ejs -
01 02 03 04 05 06 07 <% var products
= new Spree.Collections.Products() %> <% products.resetWithPagination(JSON.parse(get('products_json'))) %> <%= JST['store/templates/products/index']({ products: products }) %> <script type="text/javascript"> Spree.Data._preload.products = <%= get('products_json') %>; </script> 01. app/views/spree/products/index.jst.ejs Scribble: Example Server Side JST.EJS -
01 02 03 04 05 06 07 <% var products
= new Spree.Collections.Products() %> <% products.resetWithPagination(JSON.parse(get('products_json'))) %> <%= JST['store/templates/products/index']({ products: products }) %> <script type="text/javascript"> Spree.Data._preload.products = <%= get('products_json') %>; </script> 01. app/views/spree/products/index.jst.ejs Scribble: Example Server Side JST.EJS -
01 02 03 04 05 06 07 <% var products
= new Spree.Collections.Products() %> <% products.resetWithPagination(JSON.parse(get('products_json'))) %> <%= JST['store/templates/products/index']({ products: products }) %> <script type="text/javascript"> Spree.Data._preload.products = <%= get('products_json') %>; </script> 01. app/views/spree/products/index.jst.ejs Scribble: Example Server Side JST.EJS -
01 02 03 04 05 06 07 <% var products
= new Spree.Collections.Products() %> <% products.resetWithPagination(JSON.parse(get('products_json'))) %> <%= JST['store/templates/products/index']({ products: products }) %> <script type="text/javascript"> Spree.Data._preload.products = <%= get('products_json') %>; </script> 01. app/views/spree/products/index.jst.ejs Scribble: Example Server Side JST.EJS -
01 02 03 04 05 06 07 08 09 10
11 12 module Spree ProductsController.class_eval do helper Spree::Api::ApiHelpers def index @searcher = Config.searcher_class.new(params) @products = @searcher.retrieve_products @products_json = render_to_string(:file => 'spree/api/v1/products/index') respond_with(@products) end 01. app/controllers/spree/products_contoller_decorator.rb Scribble: Getting JSON from Actions -
01 02 03 04 05 06 07 08 09 10
11 12 module Spree ProductsController.class_eval do helper Spree::Api::ApiHelpers def index @searcher = Config.searcher_class.new(params) @products = @searcher.retrieve_products @products_json = render_to_string(:file => 'spree/api/v1/products/index') respond_with(@products) end 01. app/controllers/spree/products_contoller_decorator.rb Scribble: Getting JSON from Actions -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 source: - vendor/assets/javascripts/underscore.js - vendor/assets/javascripts/backbone.js - app/assets/javascripts/store/spree.js - app/assets/javascripts/store/paginated_collection.js - app/assets/javascripts/store/underscore_mixins.js - app/assets/javascripts/store/models/product.js - app/assets/javascripts/store/models/variant.js - ... - app/assets/javascripts/store/models/adjustment.js - app/assets/javascripts/store/collections/products.js - app/assets/javascripts/store/collections/variants.js - ... - app/assets/javascripts/store/collections/images.js layout: store/templates/layouts/spree_application 01. config/scribble.yaml Scribble: Configuration -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 source: - vendor/assets/javascripts/underscore.js - vendor/assets/javascripts/backbone.js - app/assets/javascripts/store/spree.js - app/assets/javascripts/store/paginated_collection.js - app/assets/javascripts/store/underscore_mixins.js - app/assets/javascripts/store/models/product.js - app/assets/javascripts/store/models/variant.js - ... - app/assets/javascripts/store/models/adjustment.js - app/assets/javascripts/store/collections/products.js - app/assets/javascripts/store/collections/variants.js - ... - app/assets/javascripts/store/collections/images.js layout: store/templates/layouts/spree_application 01. config/scribble.yaml Scribble: Configuration -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 source: - vendor/assets/javascripts/underscore.js - vendor/assets/javascripts/backbone.js - app/assets/javascripts/store/spree.js - app/assets/javascripts/store/paginated_collection.js - app/assets/javascripts/store/underscore_mixins.js - app/assets/javascripts/store/models/product.js - app/assets/javascripts/store/models/variant.js - ... - app/assets/javascripts/store/models/adjustment.js - app/assets/javascripts/store/collections/products.js - app/assets/javascripts/store/collections/variants.js - ... - app/assets/javascripts/store/collections/images.js layout: store/templates/layouts/spree_application 01. config/scribble.yaml Scribble: Configuration -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 if template.exist? ctx = Scribble::Context.new(@controller) compile = ctx.load_templates compile << %Q{var _view = #{EJS.compile(Pathname.new(template).read)}; var layout = JST['#{Scribble::Config.layout}']; layout()} @controller.response_body = ctx.js_context.eval(compile) else super #fallback to built rails method end 01. lib/scribble/responder.rb Scribble: ActionController::responder -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 <head data-hook="inside_head"> <title><%= get('title') %></title> <%= get('csrf_meta_tags') %> <%= get('javascript_include_tag', 'store/all') %> <script type="text/javascript"> Spree.api_key = '<%= get('api_key') %>'; $(function() { Spree.init(); }); </script> </head> <body data-hook="body"> <div class="container"> <%= JST['store/templates/shared/header']() %> <div id="wrapper" class="row" data-hook> <%= _view() %> </div> <%= JST['store/templates/shared/footer']() %> </div> </body> 01. app/assets/javascripts/store/templates/layouts/spree_application.jst.ejs Scribble: LAyout -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 <head data-hook="inside_head"> <title><%= get('title') %></title> <%= get('csrf_meta_tags') %> <%= get('javascript_include_tag', 'store/all') %> <script type="text/javascript"> Spree.api_key = '<%= get('api_key') %>'; $(function() { Spree.init(); }); </script> </head> <body data-hook="body"> <div class="container"> <%= JST['store/templates/shared/header']() %> <div id="wrapper" class="row" data-hook> <%= _view() %> </div> <%= JST['store/templates/shared/footer']() %> </div> </body> 01. app/assets/javascripts/store/templates/layouts/spree_application.jst.ejs Scribble: LAyout -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 <head data-hook="inside_head"> <title><%= get('title') %></title> <%= get('csrf_meta_tags') %> <%= get('javascript_include_tag', 'store/all') %> <script type="text/javascript"> Spree.api_key = '<%= get('api_key') %>'; $(function() { Spree.init(); }); </script> </head> <body data-hook="body"> <div class="container"> <%= JST['store/templates/shared/header']() %> <div id="wrapper" class="row" data-hook> <%= _view() %> </div> <%= JST['store/templates/shared/footer']() %> </div> </body> 01. app/assets/javascripts/store/templates/layouts/spree_application.jst.ejs Scribble: LAyout -
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20 <head data-hook="inside_head"> <title><%= get('title') %></title> <%= get('csrf_meta_tags') %> <%= get('javascript_include_tag', 'store/all') %> <script type="text/javascript"> Spree.api_key = '<%= get('api_key') %>'; $(function() { Spree.init(); }); </script> </head> <body data-hook="body"> <div class="container"> <%= JST['store/templates/shared/header']() %> <div id="wrapper" class="row" data-hook> <%= _view() %> </div> <%= JST['store/templates/shared/footer']() %> </div> </body> 01. app/assets/javascripts/store/templates/layouts/spree_application.jst.ejs Scribble: LAyout -
The BASICS: MODELS Product Variant Image Option Type Option Value
Taxonomy Taxon Order LineItem Adjustment Status -
01 02 03 04 05 06 07 08 09 10
{ user: { id: 1 }, order: { id: 1234, number: 'R716022188', item_total: '16.99', state: 'cart', ... line_items: [{...}] } } 01. /status.json snippet Status: JSON -
01 02 03 04 05 06 07 08 09 10
{ user: { id: 1 }, order: { id: 1234, number: 'R716022188', item_total: '16.99', state: 'cart', ... line_items: [{...}] } } 01. /status.json snippet Status: JSON -
01 02 03 04 05 06 07 08 09 10
{ user: { id: 1 }, order: { id: 1234, number: 'R716022188', item_total: '16.99', state: 'cart', ... line_items: [{...}] } } 01. /status.json snippet Status: JSON -
01 02 03 04 05 06 07 08 09 10
{ user: { id: 1 }, order: { id: 1234, number: 'R716022188', item_total: '16.99', state: 'cart', ... line_items: [{...}] } } 01. /status.json snippet Status: JSON -
01 02 03 04 05 06 07 08 09 10
object @taxon cache @taxon attributes *taxon_attributes node do |t| child t.children => :taxons do attributes *taxon_attributes end end 01. /api/app/views/spree/v1/taxons/show.rabl API caching: Rabl -
01 02 03 04 05 06 07 08 09 10
object @taxon cache @taxon attributes *taxon_attributes node do |t| child t.children => :taxons do attributes *taxon_attributes end end 01. /api/app/views/spree/v1/taxons/show.rabl API caching: Rabl -
01 02 03 Started GET "/api/products/search?q%5Btaxons_id_eq%5D=558398358&page=1" for 127.0.0.1 at 2012-08-18
16:56:33 +0100 Rendered spree/api/v1/products/index.rabl (3.2ms) 02. With Cache 01 02 03 Started GET "/api/products/search?q%5Btaxons_id_eq%5D=558398358&page=1" for 127.0.0.1 at 2012-08-18 16:56:05 +0100 Rendered spree/api/v1/products/index.rabl (87.2ms) 01. Without Cache Api Caching: performance -
01 02 03 Started GET "/api/products/search?q%5Btaxons_id_eq%5D=558398358&page=1" for 127.0.0.1 at 2012-08-18
16:56:33 +0100 Rendered spree/api/v1/products/index.rabl (3.2ms) 02. With Cache 01 02 03 Started GET "/api/products/search?q%5Btaxons_id_eq%5D=558398358&page=1" for 127.0.0.1 at 2012-08-18 16:56:05 +0100 Rendered spree/api/v1/products/index.rabl (87.2ms) 01. Without Cache Api Caching: performance