0

I've got an app which uses app-wide slugs (uses Slugalicious gem with Sluggable table), and have routed to these slugs by using this code:

  #Slugs
  begin  
      Slug.all.each do |s|
        begin
          get "#{s.slug}" => "#{s.sluggable_type.downcase.pluralize}#show", :id => s.slug
        rescue
        end
      end
  rescue
  end

I currently update the routes when I update the slugs model with this code:

after_save :update_routes

def update_routes
    Rails.application.reload_routes!
end

This works perfectly in dev:

Routes Work Well In Dev

The problem I'm getting is that if I update or create a new slug, Heroku doesn't update to accommodate it. It works in development, and (confusingly), it works if I do "heroku run rake routes" on Heroku. But the app just shows a 404 if I try to browse to the new URL. If I redeploy the app, all the routes work, which leads me to believe it's something to do with updating the routes app-wide

This question said it's something to do with running multiple processes on Heroku, but I've yet to find this.

Any ideas? Many thanks in advance

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Any reason you don't have a single `/:slug` route and some conflict checking to keep slugs from matching application routes? – mu is too short Oct 02 '13 at 18:35
  • Thanks for the question. What happens is that the slugs are all for specific pieces of content, and considering I have a separate admin area & the slugs are created by a single entity, I figured that I could keep on top of the routes myself. To be honest, I've not experienced that problem yet, so I've not had to write a fix :) – Richard Peck Oct 02 '13 at 18:52

1 Answers1

1

Fixed it!

There is something called an "ActiveRecord Observer" which have been depreciated since Rails 4.0. I found this website which explained what I wanted to do, but it was slightly outdated. I've included by code for rails 4.0 below:

If you're using Rails 4, use the rails-observers gem

Add the call to your environment files:

#config/application.rb (can be placed into dev or prod files if required)
config.active_record.observers = :slug_observer

Add a new observer class into your models folder:

#app/models/slug_observer.rb
class SlugObserver < ActiveRecord::Observer
  def after_save(slug)
    Rails.application.reload_routes!
    slug.logger.info("Routes Reloaded")
  end

  def after_destroy(slug)
    Rails.application.reload_routes!
    slug.logger.info("Routes Reloaded")
  end
end

The way this works is to call these bolt-on functions once the original has been run. This allowed my app to operate the function indepenent of the model in question, thus updating the routes correctly.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147