How to dynamically detect grails asset updates in production? - grails

So we have resources in the grails-app/assets folder, i.e: javascript files, stylesheets and other documents.
Some of these documents are user docs which would have to have the option of being updated in production mode. When you usually add something to this assets folder, the grails app doesn't detect this change until after redeploying the app which would cause the folder to be reprocessed.
Is there any way to detect these changes in production systems or an alternate location other than the assets folder where grails would pick up this new/updated file without re-deployment ?

Under production the most recommendable approach is to have an Apache Httpd or an NGinx server as a front end where you put the static assets. In both cases you will need configure reverse proxy on NGinx or mod_jk (depending of your Java container.).
Inclusive you may think on store large assets in a repository like S3 (if you will run on Internet).

Related

How does Rails asset pipeline do preprocessing?

In this blog, it says that assets pipeline will compile, compress, and preprocess your assets from your app/assets and then placed the out into public/assets. I don't understand the below where it says you can set up a Nginx or Apache server to preprocess your assets for you after the it already has been outputed to the public/assets. Is it saying that you can choose to have additional servers such as Apache/Nginx to do the preprocessing for your while the Rails server does the compiling/compressing?
bundle exec rake assets:precompile
This will create (by default) an assets directory in your public/
folder. It will then add all the compressed and compiled files into
that directory, in the appropriate formats and with the new digested
versions. You can then set up Nginx or Apache to server those files
directly so that Rails doesn’t have to deliver them (and run the
on-the-fly preprocessing, etc.) itself.
I don't understand the below where it says you can set up a Nginx or Apache server to preprocess your assets for you…
It doesn't say that. It does say the following:
You can then set up Nginx or Apache to server [sic] those files…
There's a difference between preprocessing and serving files. What this documentation is suggesting is that if you're using a server like nginx, you can configure it to handle requests to assets that exist in your public/assets folder. This alleviates your Rails app from handling those requests.
Pre-processing is still handled by Rails in advance of nginx coming into the picture.

How to serve a non static files in rails

I have an action, that generates a PDF files and save it in the /public/output.pdf.
When I set
config.serve_static_assets = false
this file can't be found.
What's wrong ?
From the documentation:
"config.serve_static_assets configures Rails itself to serve static
assets. Defaults to true, but in the production environment is turned
off as the server software (e.g. Nginx or Apache) used to run the
application should serve static assets instead. Unlike the default
setting set this to true when running (absolutely not recommended!) or
testing your app in production mode using WEBrick. Otherwise you won´t
be able use page caching and requests for files that exist regularly
under the public directory will anyway hit your Rails app."
Which means that if you set that to false Rails will not serve any assets from your public folder as it is assumed that a front-end web server (apache/nginx) will handle it. This lessons the load on Rails as the front-end server is much, much more efficient at serving files directly.
After testing, I came to this conclusion:
1) when using the command
rails s -e production
Rails will only serve the statics files. Any other file created after you compile your assets will not be found.
To handle this, you need to execute your application under a web server like Apache, Nginx or other. These web servers will serve this files for you.
This looks to be obvious, but not for a beginner.

Rails Asset Pipeline Path Issue

I have a Rails app running on a shared web host under a folder in my root direction called 'mintrus-ror/'. There is a symbolic link 'public_html/' that points to 'mintrus-ror/public/'. My Rails app loads in the browser but the stylesheets don't load. Looking at the rendered source I noticed the assets path it is using is '/mintrus-ror/assets/application.css'. I am trying to figure out how to change it so it does not include the 'mintrus-ror/' directory in the assets path. Any ideas?
You can try playing with the config.assets.manifest configuration option in config/environments/production.rb. There are other variables that influence this, one being the web server configuration. I've got no recent (less than six years ago) experience with shared hosts, but I've read that on some systems, you can edit the .htaccess file.
I also presume that you're running in production mode and have previously compiled the assets with rake assets:precompile during your deployment step. Capistrano does this automatically when the asset pipeline integration is turned on.
The Rails Guide on the Asset Pipeline may be useful.
Your best bet may be to host on Heroku. It's free for small sites and a lot less hassle.

Deploy static assets only to a web server with separate app server

Using Rails 3.0.7 and git, deploying with capistrano. I'm using different machines as web and app servers. I cannot deploy the application code to the web server, only the static assets--basically the public/ folder.
This would seem common but no luck searching for a best practice.
Is anything build around capistrano to handle this case? Otherwise I'm thinking that adding tasks to create the structure, but scp the public directory from the app server would be the solution.
So I assume there's a business reason you can't deploy the app to the other server?
If there isn't then just deploy the whole code
and configure your web server to just serve the public folder.
(in Apache/Passenger the configs would be exactly the same, you just wouldn't enable passenger on the static server)
That is the only simple way to do it..
otherwise you're going to cause yourself a load of headaches..
Nevertheless I'm going to make up a way to solve this.
If you do need to deploy just the static code
then I suggest you create two repositories
the app (eg. git#myserver:app.git
the static files (eg. git#myserver:static.git)
Now in your app include git#myserver:static.git as a submodule mounted at public/
Having done this, you should search standard capistrano recipes for deploying with git submodules (in particular I guess you'll want to store a local cache of the submodules, update it, then git submodule init somehow with that)
You can then have two capistrano recipes
I suggest you check out capistrano multi-stage... defining app and static as two stages
You can therefore just specify git#myserver:app.git as the repository for "app"
and git#myserver:static.git as the repository for "static"
then a simple cap app deploy:migrations && cap static deploy should do it.
but remember these will not be simultaneous
I too wish there were more established practices published. We've done ours based on the Django book which recommends making your public app directory a networked directory.
This is much better as scp only works if your public directory is static. Many apps will write things to the public directory, e.g. image generation on-the-fly. These files also need to be copied to the web server immediately.
I recommend using a NFS, Samba Share or similar, so that your public directory is actually just a networked folder, so when you write to it, it's like writing to the remote folder.
To integrate it into capistrano we do the following:
create this networked folder in shared/public
After deploy:update_code:
move content from current/public to shared/public (overriding files as needed)
remove or rename current/public then symlink current/public to shared/public
Downsides:
* doesn't remove old files (like someone earlier said)
* no real rollback option (apart from redeploying older version)
Best approach I've come up with is to in fact scp files over to the web server.

Using S3/CloudFront with Rails 3 Assets and Less CSS

This one is a mouthful! Basically I'm trying to send all of my Rails 3 assets up to the S3 Cloud and use CloudFront as the CDN to deliver it all. I already learned about configuring Rails to pull from an asset server in production mode. The problem I'm running into is finding a good way to automatically package and send everything to the cloud from a rake command or rails gem. The other problem I have is I don't know if using Less CSS with the More gem is going to screw this up. More generates a CSS file from another directory and places it in public/stylesheets. Any ideas or suggestions are much appreciated! Thanks :)
If you are pushing to Heroku and are using the Rails 3.1 assets you are all set.
In the CloudFront configuration on amazon create your distribution and set the origin to your applications URL.
Then in your production.rb file add:
config.action_controller.asset_host = "xxxxxxxxx.cloudfront.net"
The host is the host of your CloudFront distribution.
Then when you deploy make sure you are on the Cedar stack and that assets are being compiled. This will add a unique MD5 into the filenames. When a request is made to your CDN (handled automatically by the setting in your production.rb file), then the CDN will either serve up it's version of the file or pull it from the origin first. This means you don't have to push files up to the CDN, they are pulled in automatically.
If you have a file that doesn't have a unique name for some reason, then you will need to look at how to invalidate the cache in CloudFront, but other than that it's pretty easy.

Resources