Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SpreeConf 2012: Spree's Hidden Gems

Avatar for Brian Quinn Brian Quinn
February 19, 2012

SpreeConf 2012: Spree's Hidden Gems

A random collection of all things Spree Commerce related.

Avatar for Brian Quinn

Brian Quinn

February 19, 2012
Tweet

More Decks by Brian Quinn

Other Decks in Technology

Transcript

  1. We’re going to cover • Core Features • Official Extensions

    • Community Extensions • Extension Points
  2. We’re going to cover • Core Features • Official Extensions

    • Community Extensions • Extension Points • Spree Performance
  3. We’re going to cover • Core Features • Official Extensions

    • Community Extensions • Extension Points • Spree Performance • Deployment Options
  4. We’re going to cover • Core Features • Official Extensions

    • Community Extensions • Extension Points • Spree Performance • Deployment Options • More theming
  5. # Product Properties for use with Faceting # gets turned

    to #{value}_property for the facet unless defined?(PRODUCT_PROPERTY_FACETS) PRODUCT_PROPERTY_FACETS = [:brand, :shirt_fit, :gender] end Facetted Search
  6. Adding a scope module Spree class Product < ActiveRecord::Base def

    self.in_permalink(words) like_any([:permalink], prepare_words(words)) end end end
  7. core/app/controllers/.../resource_controller.rb require 'spree/core/action_callbacks' class Spree::Admin::ResourceController < Spree::Admin::BaseController ... def create

    invoke_callbacks(:create, :before) if @object.save invoke_callbacks(:create, :after) flash.notice = flash_message_for(@object, :successfully_created) respond_with(@object) do |format| format.html { redirect_to location_after_save } format.js { render :layout => false } end else invoke_callbacks(:create, :fails) respond_with(@object) end end
  8. core/app/controllers/.../resource_controller.rb require 'spree/core/action_callbacks' class Spree::Admin::ResourceController < Spree::Admin::BaseController ... def create

    invoke_callbacks(:create, :before) if @object.save invoke_callbacks(:create, :after) flash.notice = flash_message_for(@object, :successfully_created) respond_with(@object) do |format| format.html { redirect_to location_after_save } format.js { render :layout => false } end else invoke_callbacks(:create, :fails) respond_with(@object) end end
  9. core/app/controllers/.../resource_controller.rb require 'spree/core/action_callbacks' class Spree::Admin::ResourceController < Spree::Admin::BaseController ... def create

    invoke_callbacks(:create, :before) if @object.save invoke_callbacks(:create, :after) flash.notice = flash_message_for(@object, :successfully_created) respond_with(@object) do |format| format.html { redirect_to location_after_save } format.js { render :layout => false } end else invoke_callbacks(:create, :fails) respond_with(@object) end end
  10. core/app/controllers/.../resource_controller.rb require 'spree/core/action_callbacks' class Spree::Admin::ResourceController < Spree::Admin::BaseController ... def create

    invoke_callbacks(:create, :before) if @object.save invoke_callbacks(:create, :after) flash.notice = flash_message_for(@object, :successfully_created) respond_with(@object) do |format| format.html { redirect_to location_after_save } format.js { render :layout => false } end else invoke_callbacks(:create, :fails) respond_with(@object) end end
  11. Spree::HomeController.class_eval do respond_override :index => { :html => { :success

    => lambda { render :partial => "shared/some_file" } } } end Respond Override
  12. Spree::HomeController.class_eval do respond_override :index => { :html => { :success

    => lambda { render :partial => "shared/some_file" } } } end Respond Override
  13. Spree::HomeController.class_eval do respond_override :index => { :html => { :success

    => lambda { render :partial => "shared/some_file" } } } end Respond Override
  14. Spree::HomeController.class_eval do respond_override :index => { :html => { :success

    => lambda { render :partial => "shared/some_file" } } } end Respond Override
  15. Spree::HomeController.class_eval do respond_override :index => { :html => { :success

    => lambda { render :partial => "shared/some_file" } } } end Respond Override
  16. Respond Override Spree::HomeController.class_eval do def index @searcher = Spree::Config.searcher_class.new(params) @products

    = @searcher.retrieve_products respond_with(@products) do |format| format.html { render :partial => "shared/some_file" } end end end
  17. Respond Override Spree::HomeController.class_eval do def index @searcher = Spree::Config.searcher_class.new(params) @products

    = @searcher.retrieve_products respond_with(@products) do |format| format.html { render :partial => "shared/some_file" } end end end
  18. def initialize(user) user ||= Spree::User.new if user.has_role? 'admin' can :manage,

    :all else can :read, User do |resource| resource == user end can :update, User do |resource| resource == user end can :create, User can :read, Order do |order, token| order.user == user || order.token && token == order.token end ... auth/app/models/spree/ability.rb
  19. def initialize(user) user ||= Spree::User.new if user.has_role? 'admin' can :manage,

    :all else can :read, User do |resource| resource == user end can :update, User do |resource| resource == user end can :create, User can :read, Order do |order, token| order.user == user || order.token && token == order.token end ... auth/app/models/spree/ability.rb
  20. def initialize(user) user ||= Spree::User.new if user.has_role? 'admin' can :manage,

    :all else can :read, User do |resource| resource == user end can :update, User do |resource| resource == user end can :create, User can :read, Order do |order, token| order.user == user || order.token && token == order.token end ... auth/app/models/spree/ability.rb
  21. def initialize(user) user ||= Spree::User.new if user.has_role? 'admin' can :manage,

    :all else can :read, User do |resource| resource == user end can :update, User do |resource| resource == user end can :create, User can :read, Order do |order, token| order.user == user || order.token && token == order.token end ... auth/app/models/spree/ability.rb
  22. def initialize(user) user ||= Spree::User.new if user.has_role? 'admin' can :manage,

    :all else can :read, User do |resource| resource == user end can :update, User do |resource| resource == user end can :create, User can :read, Order do |order, token| order.user == user || order.token && token == order.token end ... auth/app/models/spree/ability.rb
  23. def check_authorization session[:access_token] ||= params[:token] order = current_order || Spree::Order.find_by_number(params[:id])

    if order authorize! :edit, order, session[:access_token] else authorize! :create, Spree::Order end end auth/.../orders_controller_decorator.rb
  24. def check_authorization session[:access_token] ||= params[:token] order = current_order || Spree::Order.find_by_number(params[:id])

    if order authorize! :edit, order, session[:access_token] else authorize! :create, Spree::Order end end auth/.../orders_controller_decorator.rb
  25. def check_authorization session[:access_token] ||= params[:token] order = current_order || Spree::Order.find_by_number(params[:id])

    if order authorize! :edit, order, session[:access_token] else authorize! :create, Spree::Order end end auth/.../orders_controller_decorator.rb
  26. Adding Roles > packer = Spree::Role.create :name => 'packer' =>

    #<Spree::Role id: 930089100, name: "packer"> > Spree::User.last.has_role? 'packer' => false > Spree::User.last.roles << packer > Spree::User.last.has_role? 'packer' => true
  27. Adding Roles > packer = Spree::Role.create :name => 'packer' =>

    #<Spree::Role id: 930089100, name: "packer"> > Spree::User.last.has_role? 'packer' => false > Spree::User.last.roles << packer > Spree::User.last.has_role? 'packer' => true
  28. Adding Roles > packer = Spree::Role.create :name => 'packer' =>

    #<Spree::Role id: 930089100, name: "packer"> > Spree::User.last.has_role? 'packer' => false > Spree::User.last.roles << packer > Spree::User.last.has_role? 'packer' => true
  29. Adding Roles > packer = Spree::Role.create :name => 'packer' =>

    #<Spree::Role id: 930089100, name: "packer"> > Spree::User.last.has_role? 'packer' => false > Spree::User.last.roles << packer > Spree::User.last.has_role? 'packer' => true
  30. Adding abilities module Spree class PackerAbility include CanCan::Ability def initialize(user)

    if user.has_role? 'packer' can [:read, :update], Shipment end end end end Ability.register_ability(Spree:::PackerAbility)
  31. Adding abilities module Spree class PackerAbility include CanCan::Ability def initialize(user)

    if user.has_role? 'packer' can [:read, :update], Shipment end end end end Ability.register_ability(Spree:::PackerAbility)
  32. Adding abilities module Spree class PackerAbility include CanCan::Ability def initialize(user)

    if user.has_role? 'packer' can [:read, :update], Shipment end end end end Ability.register_ability(Spree:::PackerAbility)
  33. Adding abilities module Spree class PackerAbility include CanCan::Ability def initialize(user)

    if user.has_role? 'packer' can [:read, :update], Shipment end end end end Ability.register_ability(Spree:::PackerAbility)
  34. Adding abilities module Spree class PackerAbility include CanCan::Ability def initialize(user)

    if user.has_role? 'packer' can [:read, :update], Shipment end end end end Ability.register_ability(Spree:::PackerAbility)
  35. Versionfile "1.0.x" => { :branch => 'master' } "0.70.x" =>

    { :tag => "v1.2", :version => "1.2" } "0.60.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.50.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.30.x" => { :version => "1.0" }
  36. Versionfile "1.0.x" => { :branch => 'master' } "0.70.x" =>

    { :tag => "v1.2", :version => "1.2" } "0.60.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.50.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.30.x" => { :version => "1.0" }
  37. Versionfile "1.0.x" => { :branch => 'master' } "0.70.x" =>

    { :tag => "v1.2", :version => "1.2" } "0.60.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.50.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.30.x" => { :version => "1.0" }
  38. Versionfile "1.0.x" => { :branch => 'master' } "0.70.x" =>

    { :tag => "v1.2", :version => "1.2" } "0.60.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.50.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.30.x" => { :version => "1.0" }
  39. Versionfile "1.0.x" => { :branch => 'master' } "0.70.x" =>

    { :tag => "v1.2", :version => "1.2" } "0.60.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.50.x" => { :ref => "5172de86dd46905e6d60", :version => "1.1" } "0.30.x" => { :version => "1.0" }
  40. Transactions: Availability: Elapsed time: Data transferred: Response time: Transaction rate:

    Throughput: Concurrency: Successful transactions: Failed transactions: Longest transaction: Shortest transaction: 1000 hits 100.00 % 189.45 secs 3.89 MB 17.98 secs 5.28 trans/sec 0.02 MB/sec 94.90 1000 0 21.85 1.08
  41. preload_app true GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true before_fork do |server,

    worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end config/unicorn.rb
  42. preload_app true GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true before_fork do |server,

    worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end config/unicorn.rb
  43. Transactions: Availability: Elapsed time: Data transferred: Response time: Transaction rate:

    Throughput: Concurrency: Successful transactions: Failed transactions: Longest transaction: Shortest transaction: 1000 hits 100.00 % 39.94 secs 3.72 MB 3.29 secs 25.04 trans/sec 0.08 MB/sec 82.35 1000 0 7.67 0.48 1000 hits 100.00 % 189.45 secs 3.89 MB 17.98 secs 5.28 trans/sec 0.02 MB/sec 94.90 1000 0 21.85 1.08 Before After
  44. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet
  45. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source
  46. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source • Installed Rubg Gems, Git, Nginx, MySQL, Imagick, Bundler, Foreman, etc
  47. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source • Installed Rubg Gems, Git, Nginx, MySQL, Imagick, Bundler, Foreman, etc • Cloned Spree 1.0.0.rc demo app
  48. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source • Installed Rubg Gems, Git, Nginx, MySQL, Imagick, Bundler, Foreman, etc • Cloned Spree 1.0.0.rc demo app • Ran bundle install
  49. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source • Installed Rubg Gems, Git, Nginx, MySQL, Imagick, Bundler, Foreman, etc • Cloned Spree 1.0.0.rc demo app • Ran bundle install • Bootstrapped sample db & compiled assets
  50. In case you missed it • A blank Ubuntu 10.04

    LTS Cloud Server • Installed Puppet • Compiled Ruby 1.9.3 from source • Installed Rubg Gems, Git, Nginx, MySQL, Imagick, Bundler, Foreman, etc • Cloned Spree 1.0.0.rc demo app • Ran bundle install • Bootstrapped sample db & compiled assets • All with one command!