engine's static assets

Hi all.

Currently, rails 2.3 engines can't have (or override) static files in their own public/ directory like they do with views, controllers, etc.

Recently playing with rack, I implemented the following middleware:

http://gist.github.com/175518

As you can see, in environment.rb the middleware gets initialized with the asset directories (which exists) from loaded plugins (may be there is a way to check if those are engines?)

The middleware sees if the requested file is in one of the engines providing a public/ directory. The first one that matches is returned (an overlay just like the other components of engines work), if not, the request is just passed to the application.

This feature is really useful. Now that I see how easy was to implement, I wonder if it is a valid solution, and if the concept could be used to add support in Rails itself for this, or if you guys see a problem with this approach?

Thanks Duncan

I guess one drawback here is that the engine assets won't be delivered
directly by the frontend server, causing a hit (although a cheap one)
to the application, no? Do you have a cache layer in front of this?

One of the approaches I saw used in an old attachment plugin - don't
remember which one - was to check this in an asset tag helper. The
helper in this case could ne patched to return an engine override if
one exists, which would allow the frontend to continue serving the
assets.

-Matt

How about a task ran after a (theoretical) script/engine install?

This task would copy assets from public/[images|stylesheets|javascripts]/engine-name in an engine and then put them in the relevant directories in public. You’d then still get them accessible, but without the performance hit. public/images/engine-name would end up in the same spot, so you then can do <%= image_tag “engine-name/image” %> still to get access. I think this would also solve the (potential) problem of apps and engines having identically named files.

The engines plugin already does this; each time the server started up
it copies whatever is in engine-name/assets into public/plugin_assets/ engine-name, and it adds image_path and image_tag, so you call image_tag "image" :plugin =>
"engine-name" to access "image" for that plugin.

see http://github.com/lazyatom/engines/blob/bc5cd970e048dfe5e0e8c06ccf4969bd0d1299be/lib/engines/rails_extensions/asset_helpers.rb

I’d prefer it if:

  1. assets were put in the relevant directories, rather than “polluting” the public directory with more folders. So all images for an engine would go in public/images/engine-name rather than public/engine-name/images.

  2. People just did image_tag “engine-name/image”, as it’s shorter and I’m all for laziness.

In our experience copying assets sucks bad. At least on *nix systems it should just symlink them, or have a separate task for that.

Obviously with copies when you work on your engine assets you

  • have to do that in the public/ folder and

  • then remember to sync stuff back to the engine when committing

… which is something you never have to think about anywhere else in Rails. We’ve lost changes this way a couple of times.

:slight_smile:

Yes, and I also think it may work for a "deployed" web application. But we are developing a remote configuration tool which is "packaged" and therefore having the application to modify the public/ directory is no option.

Duncan