Rails 3.1 assets not recognizing new images uploaded by rmagick until server restart - ruby-on-rails-3.1

I have my Rails 3.1.0 application running with passenger in production environment and I have a section where the application allows the user to change his profile picture so I upload the image using an ajax uploader and in my controller I upload the file and generate different sizes for the image with rmagick then I render the new image with an image_tag but the application won't show the image till I restart the server.
What I get is No route matches [GET] "assets/path/to/image.png"
If I restart the server It will show the image, but obviously I can't be restarting the server every once a user uploads a new image.
How can I solve the keeping the assets working the right way?

The Rails asset pipeline is really meant for structural / design images, such as backgrounds, icons, banners, etc..). Dynamic assets should go in the public directory [source below]
It's probably a good idea to serve static assets through Nginx or Apache or whatever your web-server is, or place them in the public directory of your Rails app.
That should solve your problem right there.. e.g. make a separate path for static assets into which you upload those images with rmagick / carrierwave, or whatever gem you prefer.
The asset pipeline only knows about images which are present during start-up. So separating static / uploaded assets into a separate directory , and serving it directly through the web-server, will help -- it should also be much faster.
you'll need something like this in your configuration:
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# UNCOMMENT the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
More General:
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
http://guides.rubyonrails.org/asset_pipeline.html
Rails 3.1: Should File Uploads be added to asset pipeline?
Regarding serving images outside asset pipeline:
http://mrjaba.posterous.com/rails-31-asset-pipeline-with-nginx-and-passen
http://trackingrails.com/posts/rails-31-and-asset-pipeline-problems-with-apache
http://pastebin.com/kC4Ba40U
https://github.com/defunkt/resque/issues/418

Related

how to serve images to a single page application with a sinatra API?

I am trying to serve images to my client application with my Sinatra API
when I use this route, it triggers the file download prompt in my browser rather than loading up an image file, how would I go about serving up an image?
get '/images/:project/:img' do
send_file(ProjectPhotos.serve_file(params)) # => triggers a download of file in browser
end
need to add open from the OpenURI library
get '/images/:project/:img' do
send_file open(ProjectPhotos.serve_file(params), type: 'image/jpeg', disposition: 'inline')
end
For serving static images you should use the public folder in Sinatra application root. All files in public folder are served by Sinatra web server without any code needed and the public directory omitted from url.
So "public/yourimage.jpg" is available from "www.yoursite.com/yourimage.jpg"
For more info look at Sinatra documentation.

How to point Flask static to Amazon S3 URLs?

I have a Flask app hosted on Heroku but want the static files to be served from Amazon S3.
In my templates I use url_for() for all references to static files. In the initialization of the Flask app I then want to put
app = Flask(__name__, static_url_path="http://my-bucket.s3.amazonaws.com")
to make sure instead of mysite.com/static/, http://my-bucket.s3.amazonaws.com/static/ is used. However I get this error:
ValueError: urls must start with a leading slash
If I change it to a value with a leading slash it works, but I want the static URL to point to S3, an external domain so it needs to start with http://.
What am I doing wrong? How can I use S3 for static files with Flask and Heroku?
If you are using any of the static_* options to the Flask object, it is assuming that it'll be responsible for serving those files. A static route is configured that serves both as the view to serve the static files and as the url_for() target to generate the URLs.
So, with Flask alone, you'd have to replace all url_for('static', ...) calls with hardcoded URLs to your CDN instead.
Instead, you should switch to using Flask-CDN, a handy Flask add-on to handle seamless switching between static files hosted by Flask and by a CDN:
from flask_cdn import CDN
app = Flask(__name__)
cdn = CDN(app)
and set the CDN_DOMAIN configuration option to http://my-bucket.s3.amazonaws.com when deploying to production.
In debug mode, url_for() will then generate the old /static/.. urls for Flask to handle, in production mode, url_for() prefixes those urls with the CDN_DOMAIN value. If the latter is left to the default None setting, no such URL alterations take place, making it possible to run Flask locally with debug switched off as needed.
Note that the behaviour of url_for() is only altered for Jinja templates; if you need to generate static URLs in your views, you'll have to swap flask.url_for() out for flask_cdn.url_for().

Rails 4 - Asset fingerprints spontaneously go missing from asset paths

Configuration: Rails 4, HTML, CSS, on Heroku.
I have a Rails 4 app that has been in production for five months. Here's what's in my production.rb:
config.serve_static_assets = false
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
config.assets.enabled = true
config.assets.initialize_on_precompile = true
config.action_controller.asset_host = "//dynasfakeurl.cloudfront.net"
Whenever I push to production, I clean my assets using rake assets:clean, then precompile them using rake assets:precompile. This fingerprints my assets, and pushes it directly to my S3 static file bucket, which are served via cloudfront. I then push my app live to Heroku.
On the .html.erb homepage, I call my static files via Rails tags like this:
<%= image_tag "picture.png" %>
<%= stylesheet_link_tag "application" %>
Which render correctly using fingerprints. For example, the second one most recently generated this asset path: http://dynasfakeurl.cloudfront.net/assets/application-17892abdffc77f1fb1be125bab.css
Usually, this works great. However, I've had a problem, twice now, where after 12-16 hours of my last push, all of my asset paths spontaneously lose their fingerprints. For example, the stylesheet tag last generated this asset path: http://dynasfakeurl.cloudfront.net/stylesheets/application.css. Which doesn't exist. Thus, when I load the page, it fails to load the assets.
I've been stuck for the past few hours trying to debug this, but can't figure out why my asset paths would spontaneously, without me pushing anything, lose their fingerprints in production.

Why won't Rails find my assets?

When in production mode, rails can't seem to find any precompiled assets from the asset pipeline.
I'm using rails 3.2.0 and ruby 1.9.3 running inside RVM on CentOS. No additional web server is running in conjunction with this application. The application was only recently updated to use the asset pipeline, as it was originally a rails 3.0 app.
After running
rake assets:clean
rake assets:precompile
I see the hashed content in public/assets, as I would expect. The hashes at the end of the files match those I see in the page source.
Yet at runtime, here's what I see for every asset Rails tries to serve:
Started GET "/assets/application-892c6227e631daf9a8e041b1d4d002ec.css" for 75.149.58.169 at 2012-03-14 11:42:43 -0700
ActionController::RoutingError (No route matches [GET] "/assets/application-892c6227e631daf9a8e041b1d4d002ec.css"):
I'm not referring to the folder that each asset is housed in; all references to assets look like these:
//css:
.class {
background: url(asset.png) no-repeat;
}
//erb:
<%= image_tag "asset.png" %>
<%= link_to "page", :class => "class" %>
Asset pipeline pertinent settings in production.rb:
config.serve_static_assets = false
config.assets.enabled = true
config.assets.compress = true
config.assets.debug = false
config.assets.compile = false
config.assets.digest = true
And lastly, asset settings from config/application.rb:
config.assets.enabled = true
config.assets.version = '1.0'
The user starting the rails server process has read, write and execute permissions on public/assets, so I don't think it's a permissions issue. Have I missed a configuration step?
Edit
I noticed that there are no errors stating that assets are not precompiled, so I tried to access a stylesheet from the web page by appending"/assets/application-892c6227e631daf9a8e041b1d4d002ec.css" to the end of the host path:
http://www.myapp.com"/assets/application-892c6227e631daf9a8e041b1d4d002ec.css"
This worked and the stylesheet opened.
Further researching of this issue yielded this SO article:
application.css not being served as an asset
It seems
config.serve_static_assets = false
Is an incorrect setting as long as my Rails application is not running behind Apache or nginx
I had this same problem, but I note that your stylesheet is pointing to the non-fingerprinted, non-cached version of the files. If you are using the asset pipeline, in order to take advantage of it, you need to use the helpers that point to the fingerprinted, cached version of the files. To do this, you'll need to either embed erb in your css file, or use sass.
Incorrect:
.class {
background: url(asset.png) no-repeat;
}
Correct (uses sass):
.class
background: image-url('asset.png') no-repeat
For more info, see here: http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
If you don't care about the performance issues, you can get away with using the non-cached versions until you upgrade to Rails 4 or Rails 3.2.16, because those versions introduce breaking changes that force you to use the asset pipeline (and its corresponding syntax). If you don't use the new syntax, the non-cached versions will not work at all on production.

Rails 3.1 - How to separate CSS/JS between normal app and active_admin gem

My application is deployed on Rails 3.1 and on Heroku.
1. In production.rb, if I have config.assets.compile = true only then active_admin works. However, in production, I want config.assets.compile = false for normal application CSS and JS. The active admin module will be used only by administrator so it can be slow.
2. Moreover, since I installed active_admin gem my normal CSS has got terribly disturbed.
Hence, I want to somehow split the CSS and JS of active_admin and normal application so that:
1. Only when I hit localhost:3000/admin then CSS and JS of active admin hits and that of normal app does not. When I am on any other URL, then CSS and JS of normal app hits but active admin's does not.
2. I can config.assets.compile = false to normal app CSS and JS while make it config.assets.compile = true for active_admin alone.
Is this possible?
The good news is that you can have .compile set to false for both, and have both run fast!
Active admin uses its own manifests that start with 'active_admin'. By default these won't be precompiled by Rails.
To get them precompiled you need to add these files to the precompile array in production.rb:
config.assets.precompile += ['active_admin.js', 'active_admin.css']
This will create the files in the /assets folder and allow you to set .compile to false all the time.
Don't forget to also set:
config.assets.digest = true

Resources