Overriding routes from another Rails engine (Spree)

1,748 views
Skip to first unread message

Thomas Mulloy

unread,
Jul 14, 2014, 9:39:27 PM7/14/14
to alche...@googlegroups.com
i'm using Alchemy + Spree, and for the most part I would like the Spree routes to take precedence over Alchemy's, so I've mounted Spree before Alchemy and everything works as I want, except for one thing. 

I'm trying to override the Spree routes for the products resource which is defined here https://github.com/spree/spree/blob/2-3-stable/frontend/config/routes.rb#L5 so that Alchemy will handle the "products(/:id)" routing. Here is what I've attempted to do:


Rails.application.routes.draw do

  # override Spree root path
  root 'alchemy/pages#show'

  # *** override Spree products ****
  get '(/:lang)/products/*urlname(.:format)', 
    to: 'alchemy/pages#show',
    constraints: {
      lang: /[a-z]{2}(-[a-z]{2})?/
    }

  # Spree routes take precedence over Alchemy
  mount Spree::Core::Engine, at: '/'
  
  # Alchemy as a catch-all
  mount Alchemy::Engine, at: '/'

end

but the one issue preventing it from working (i believe) is that the param `urlname` will not be prefixed with the parent `products` to form `products/product-slug`, instead of course the only value that comes through for the urlname param is that segment, eg. `product-slug`. Is there a way to prefix the urlname param at the router level? or what would be a nice way of achieving this level of override?

thank you,

thomas

Thomas Mulloy

unread,
Jul 15, 2014, 3:50:15 PM7/15/14
to alche...@googlegroups.com
I feel like this may be a bit of overkill, but it seems to be working to achieve what I want. The general idea is to remove all of the Spree frontend routes, then re-introduce the necessary ones.

in my `application.rb` 

class Application < Rails::Application
  config.to_prepare do
    ...

    initializer "delete_spree_frontend_routes", after: "add_routing_paths" do |app|
      app.routes_reloader.paths.delete_if{ |path| path.include?("spree_frontend") }
    end
  end
end

then with the same `routes.rb` as above, less the "*** override Spree products ****"

Rails.application.routes.draw do

  # override Spree root path
  root 'alchemy/pages#show'

  # Spree routes take precedence over Alchemy
  mount Spree::Core::Engine, at: '/'
  
  # Alchemy as a catch-all
  mount Alchemy::Engine, at: '/'

end

I've appended the original Spree frontend routes https://github.com/spree/spree/blob/2-3-stable/frontend/config/routes.rb less the `resources :products, :only => [:index, :show]`

Spree::Core::Engine.add_routes do

  root :to => 'home#index'

  get '/locale/set', :to => 'locale#set'

  # non-restful checkout stuff
  patch '/checkout/update/:state', :to => 'checkout#update', :as => :update_checkout
  get '/checkout/:state', :to => 'checkout#edit', :as => :checkout_state
  get '/checkout', :to => 'checkout#edit' , :as => :checkout

  populate_redirect = redirect do |params, request|
    request.flash[:error] = Spree.t(:populate_get_error)
    request.referer || '/cart'
  end

  get '/orders/populate', :to => populate_redirect
  get '/orders/:id/token/:token' => 'orders#show', :as => :token_order

  resources :orders, :except => [:index, :new, :create, :destroy] do
    post :populate, :on => :collection
  end

  get '/cart', :to => 'orders#edit', :as => :cart
  patch '/cart', :to => 'orders#update', :as => :update_cart
  put '/cart/empty', :to => 'orders#empty', :as => :empty_cart

  # route globbing for pretty nested taxon and product paths
  get '/t/*id', :to => 'taxons#show', :as => :nested_taxons

  get '/unauthorized', :to => 'home#unauthorized', :as => :unauthorized
  get '/content/cvv', :to => 'content#cvv', :as => :cvv
  get '/content/*path', :to => 'content#show', :as => :content
  get '/cart_link', :to => 'store#cart_link', :as => :cart_link
end

Reply all
Reply to author
Forward
0 new messages