Reloading Routes with a Rake Task

This may be more Rails than Radiant but can anyone give me a hand with
this one…

How do I execute ActionController::Routing::Routes.reload! for a running
instance of Radiant from a Rake task? It works fine if I trigger it
from within the app but I need it to run from Rake and it seems that
Rake runs in a separate process.

Background for those who want it:

In the SnS extension, I define custom routes for CSS and JS files to
route to my own TextAssetSiteController. I did this to prevent coupling
too tightly with SiteController.

Well, now I’m upgrading the functionality to allow admins to change the
configuration on the fly using Rake tasks. This includes settings that
require the route to be updated and I don’t know how to get Rake to run
ActionController::Routing::Routes.reload! for a running instance of
Radiant.

-Chris

Nevermind. I wound up going the route of alias_method_chain-ing
SiteController’s #show_page method. It makes things more tightly
coupled to Radiant but it’s also closer to how it’d be if built-in.

If anybody else out there is already using alias_method_chain on this
method in your extension, let me know. I’d sure love to avoid a 20 car
pileup there if a user has multiple extensions installed.

-Chris

Chris P. wrote:

Nevermind. I wound up going the route of alias_method_chain-ing
SiteController’s #show_page method. It makes things more tightly
coupled to Radiant but it’s also closer to how it’d be if built-in.

If anybody else out there is already using alias_method_chain on this
method in your extension, let me know. I’d sure love to avoid a 20 car
pileup there if a user has multiple extensions installed.

-Chris

Could you simply add a before filter in that controller instead? before
filters can stack up without overriding other filters in other
extensions. And seems cleaner than an alias_method_chain

before_filter :reload_routes, :only => :show

private
def reload_routes
ActionController::Routing::Routes.reload!
end

And yes, since rake loads up its own rails process, it wont work for
this. The only way I can see send a message like this into a rails form
outside is via http. So your rake task would send a request to
http://mysite.com/reload_routes” which would do what you want.

But that gets hairy too. Lets say you have multiple mongrels, 1 out of
4 got that request, and reloads its routes. All other mongrel don’t
have their routes reloaded.

In general, I don’t think you can use rake very well to modify the state
of an already running rails process. You definitely want a hook in your
extension to load the routes as needed. And remember that just because
you updated the routes in the rails process that handled the admin
requested route change doesn’t mean its been updated in the other
processes. This is a bug that would work fine in development mode with
a single process, and suddenly cause weird issues in a more distrubed
production deployment.

I’ve made about 5 websites with radiant so far and I guess most of
them I just started with a simple blog or empty. Today I started with
the more filled in version and discovered how this sidebar page part
is being used. It’s brilliant! Really. I’ve been using snippets to
attempt the same thing but their not nearly as flexible. I’m forever
learning new things about Radiant with each new website I make with
it. Thanks for all your thoughtful work guys. I love using this
system.

Steven

Chris P. wrote:

My question was originally tied to approach #1. I could use a Rake task
to change the “javascript_directory” but couldn’t get the
already-running server to reload its routes.

Now I’m working on having an augmented SiteController#show_page action
process the whole thing (#2). If I use a before_filter to call my
#show_text_asset action and it finds and renders the script/stylesheet,
how to I then prevent things from proceeding on to #show_page?

Will rails let you set up a before_filter against only one action,
anyway?

-Chris

I believe, in any rails before_filter if you call render or redirect_to,
it halts the filter chain and prevents further execution. This is
commonly used for access control. So as long as you render something,
it should works just as you need it too. Unless radiant does something
funky with rendering that I dont know about.

before_filter :authorize
def authorize
redirect_to login_url unless admin_logged_in?
end

And yes, you can fine tune your before filters by passing action names
to the :only or :except keys of the options hash.

before_filter :foo, :only => [:index, :show]
before_filter :foo, :except => [:create]

They are pretty flexible creatures.

Hmm. Will give that a whirl then. I’ll let you know. Thanks.

-Chris

If a plain redirect or render doesn’t work, return false as well.
That’ll halt the chain for sure.

Sean

Actually, I was just thinking about using a before filter too. I hate
being so obtrusive with alias_method_chain, but I’m not sure a
before_filter will work.

The job I’m trying to do here is find and render css and js files and,
if the file’s not found, let SiteController try to render it as a page
(or render the 404 for me). There are two approaches (that I can think
of anyway):

  1. Set up a route to catch “#{javascript_directory}/*filename”
    (similar for stylesheets) and send it to my controller to look for
    and render the file. If my controller can’t find the file, pass
    things along to SiteController’s #show_page method. (This is how
    SnS did it originally)

  2. Don’t use any cust6m routing but instead piggyback on
    SiteController’s #show_page method. Instead of site controller
    looking for pages, I’d first steal the processing and try to match
    the params[:url] against the javascript_directory. If it matches
    a js or css file -> render it. If the file can’t be found, return
    processing back to your regularly scheduled action (#show_page)
    and let it do its thing.

My question was originally tied to approach #1. I could use a Rake task
to change the “javascript_directory” but couldn’t get the
already-running server to reload its routes.

Now I’m working on having an augmented SiteController#show_page action
process the whole thing (#2). If I use a before_filter to call my
#show_text_asset action and it finds and renders the script/stylesheet,
how to I then prevent things from proceeding on to #show_page?

Will rails let you set up a before_filter against only one action,
anyway?

-Chris