Question

I have created a route plus controller for doing dynamic css in ruby on rails as per the instructions here:

http://www.misuse.org/science/2006/09/26/dynamic-css-in-ruby-on-rails/

It took some changing to account for a newer version of ruby on rails, but the problem comes in with the routes.rb entry. The original entry was this:

  # dynamic CSS (stylesheets)
  map.connect 'rcss/:rcssfile',
    :controller => 'rcss',
    :action => 'rcss'

This did not work with a newer version of RoR, and I found this solution to work:

  # dynamic CSS (stylesheets)
  map.connect 'rcss/:rcssfile.css',
    :controller => 'rcss',
    :action => 'rcss'

However, now I was bummed that I couldn't get a catch-all filetype extension handler. The request had to have the .css extension. Playing around with it further I came up with this:

  # dynamic CSS (stylesheets)
  map.connect 'rcss/:rcssfile.:format',
    :controller => 'rcss',
    :action => 'rcss'

So this is much better. Now I could potentially request a file that ended in .foobar or whatever and match it with a handler. Not that I would necessarily, but it's more about understanding everything.

So then I tried creating a file that looked something like "foo.net.rcss" . Now it would seem that the first dot messes everything up. "no routes match rcss/foo.net.css". My questions are as follows:

  1. How can I match any filename and any extension regardless of how many dots are in the filename?

  2. Why does the first example not work in later RoR versions?

  3. Why do multiple dots screw up the match?

Thanks in advance for any help.

------- update -------

I am using Rails 3.0.5 . As per some more research I can shorten the syntax to:

match 'rcss/:rcssfile', :to => 'rcss#rcss'

This is the equivalent of the first example that did not seem to work, however using this syntax it works just as expected.

match 'rcss/:rcssfile:.:format', :to => 'rcss#rcss'

This also works just like my previous example #3, however it still has the problem of not matching a file with multiple periods.

Was it helpful?

Solution

It would seem that labeling a standard ":paramater" takes special consideration for the period character. ":parameter" will match a path with up to one period, ":parameter.:extension" will match a path with up to two periods, but the :extension will be only what's between the two periods, etc.

A way around this is to use what is called "Route Globbing", which uses an asterisk instead of a colon:

match 'rcss/*rcssfile', :to => 'rcss#rcss'

The only caveat is that this will match ANYTHING after the asterisk, including subdirectories. As such, you want to make sure that this does not accidentally expose any secure files or accidentally render things unintentionally.

OTHER TIPS

Use a regex to match the filename?

map.connect 'rcss/:rcssfile',
  :controller => 'rcss',
  :action => 'rcss',
  :requirements => {:rcssfile => /.+\.rcss/ }

This would match (anything).rcss - you could adjust the regex for various suffixes.

I used this for a general case when you don't know the extension:

get '/uploads/:basename.:extenstion', to: 'controller#action', basename: /.*(?=\.[\w\d]+$)/
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top