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

SpreeConf 2012: Spree's Hidden Gems

Brian Quinn
February 19, 2012

SpreeConf 2012: Spree's Hidden Gems

A random collection of all things Spree Commerce related.

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!