image upload not working on heroku with s3 - ruby-on-rails

I'm using the Paperclip gem to handle image uploads on my Rails app. Everything works great in development but when I upload an image on the heroku app I get the "Something went wrong" error. I checked the heroku logs and I don't see any error messages. However, the one difference I noticed between dev and heroku is that the dev logs shows that the "begin..insert into...etc" SQL shows, whereas in heroku the logs don't show any SQL. It doesn't even get to write to the database.
The heroku logs only show the "Parameters" and some commands afterwards:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"****", "show"=>{"name"=>"test", "description"=>"this is a description", "cover"=>#<ActionDispatch::Http::UploadedFile:0x007f3776700fd0 #tempfile=#<Tempfile:/tmp/RackMultipart20140427-2-1431xte>, #original_filename="bc_top.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"show[cover]\"; filename=\"bc_top.png\"\r\nContent-Type: image/png\r\n">, "thumbnail"=>#<ActionDispatch::Http::UploadedFile:0x007f3776700eb8 #tempfile=#<Tempfile:/tmp/RackMultipart20140427-2-al452c>, #original_filename="bc_cover.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"show[thumbnail]\"; filename=\"bc_cover.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Add show"}
Then it shows some other commands but no errors:
Command :: file -b --mime '/tmp/bdccc4601dd7e6aea5035c03817bca8020140427-2-2i17k4.png'
2014-04-27T16:06:34.040235+00:00 app[web.1]: Command :: file -b --mime '/tmp/68aaf40ebdc9b119d96bb0b3ff13118020140427-2-189rb23.png'
2014-04-27T16:06:34.150632+00:00 app[web.1]: Command :: file -b --mime '/tmp/bdccc4601dd7e6aea5035c03817bca8020140427-2-bfdlsj.png'
2014-04-27T16:06:33.966054+00:00 app[web.1]: vendor/bundle/ruby/2.1.0/gems/rack-1.5.2/lib/rack/handler/webrick.rb:60:in `service'
2014-04-27T16:06:33.966069+00:00 app[web.1]: Started POST "/shows" for 76.***.***.** at 2014-04-27 16:06:33 +0000
2014-04-27T16:06:33.966071+00:00 app[web.1]: Processing by ShowsController#create as HTML
2014-04-27T16:06:34.099317+00:00 app[web.1]: Command :: file -b --mime '/tmp/68aaf40ebdc9b119d96bb0b3ff13118020140427-2-5r5s9s.png'
2014-04-27T16:06:34.446474+00:00 heroku[router]: at=info method=POST path=/shows host=app.herokuapp.com request_id=1bc386a4-147c-403a-9b88-55fe488ec4e3 fwd="76.***.***.**" dyno=web.1 connect=2ms service=676ms status=500 bytes=919
I'm completely stumped. No errors! Here are the relevant files:
production.rb
appName::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# 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 = true
# Generate digests for assets URLs
config.assets.digest = true
config.assets.precompile = [ /\A[^\/\\]+\.(ccs|js)$/i ]
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
# config/environments/production.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
end
application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module appName
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
# Use SQL instead of Active Record's schema dumper when creating the database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.serve_static_assets = true
end
end
initializer/paperclip.rb
Paperclip::Attachment.default_options[:storage] = :s3
Paperclip::Attachment.default_options[:s3_protocol] = 'http'
Paperclip::Attachment.default_options[:s3_credentials] =
{ :bucket => ENV['AWS_BUCKET'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'] }
Show model (object with the file attachments)
class Show < ActiveRecord::Base
has_many :episodes
has_attached_file :thumbnail
validates_attachment_content_type :thumbnail, :content_type => /\Aimage\/.*\Z/
has_attached_file :cover
validates_attachment_content_type :cover, :content_type => /\Aimage\/.*\Z/
end
I double checked my heroku config vars and they match up fine. I have this working on a different Rails 3 app and I'm wondering if I am missing something on this new Rails 4 app. Any ideas?
Thanks!

Heroku logs don't always help.
For your purposes since you're just getting started I would recommend setting your heroku app to "development" mode so you can see verbose error messages.
heroku config # Should return a list of your current environment, including RACK_ENV=production
heroku config:add RACK_ENV=development # now you'll get verbose error messages
heroku config:add RACK_ENV=production # set this back when you're done debugging
Check out the logs and tell us what you see.
But I would recommend that you use direct upload to S3. I've written about uploading images to S3 over here (http://blog.jobspire.net/uploading-images-to-heroku/). So do take a look.
Also Heroku has a read-only filesystem. That means Paperclip cannot save uploaded files to any place within Heroku. That might be the issue.
If you would like to be able to upload files to an application hosted
on Heroku, then you must either store the files as binary blobs within
your database or you must use a separate service to store the files.
If you are looking for a separate service, Paperclip has built-in
support for integrating with Amazon S3.
See the relevant Heroku docs.

Related

Rails 5.2 asset helpers not including fingerprint digests

I am in the process of upgrading our product from rails 4.1 to 5.2. I'm hung up on what appears to be an asset pipeline related issue. When I load the app in our browser, I see the following error in the server log and the app is missing all styling and javascript code that it normally has.
DEPRECATION WARNING: The asset application.js" is not present in the asset pipeline.Falling back to an asset that may be in the public folder.
This behavior is deprecated and will be removed.
To bypass the asset pipeline and preserve this behavior,
use the `skip_pipeline: true` option.
When I wget the index.html of the application, I see that all of the images and javascript urls are lacking the fingerprint digest they should have. Interestingly enough, they do have the S3 asset_host we have, so they are in fact being processed by the helpers.
To demonstrate, I have two servers which have identical configurations, but one is running 4.1 and the other 5.2. On both, I am using S3 as an asset_host and digest is turned on. I've run the following commands in their consoles:
=== Rails 4 ===
Loading qatest environment (Rails 4.1.0)
irb(main):001:0> Rails.application.config.action_controller.asset_host
=> "https://redacted.s3.amazonaws.com"
irb(main):002:0> Rails.application.config.assets.digest
=> true
irb(main):003:0> ActionController::Base.helpers.asset_path('application.js')
=> "https://redacted.s3.amazonaws.com/assets/application-042f2014ca329c79c304ab1332557040d3f7b922247202f40c28acc950f30ef8.js"
=== Rails 5 ===
Loading sean environment (Rails 5.2.1)
irb(main):001:0> Rails.application.config.action_controller.asset_host
=> "https://redacted.s3.amazonaws.com"
irb(main):002:0> Rails.application.config.assets.digest
=> true
irb(main):003:0> ActionController::Base.helpers.asset_path('application.js')
=> "https://redacted.s3.amazonaws.com/application.js
As requested, production.rb
require "#{File.dirname(__FILE__)}/includes/s3_assets"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb
config.eager_load = true
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = false
config.log_level = ENV['SHOW_SQL'] != 'false' ? :debug : :info
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = true
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: Rubber.config.email_username,
password: Rubber.config.email_password,
address: Rubber.config.email_server,
port: Rubber.config.email_port,
enable_starttls_auto: true, # detects and uses STARTTLS
authentication: 'login' # Mandrill supports 'plain' or 'login'
}
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
# config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fall back to assets pipelin if a precompiled asset is
# missed.
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
config.assets.enabled = true
# Nginx will serve as an asset proxy to s3, where assets are
# stored.
config.serve_static_assets = false
# instead of bundling the assets, include multiple css style includes
config.assets.debug = true
config.assets.logger = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# NB: The exclusion of any protocol in the asset host declaration above will allow browsers to choose the transport mechanism on the fly.
# So if your application is available under both HTTP and HTTPS the assets will be served to match.
configure_s3_assets config
config.action_controller.asset_host = "https://#{Rubber.config.s3_assets_bucket}.s3.amazonaws.com"
config.action_mailer.default_url_options = { :host => Rubber.config.external_host }
config.sequel.search_path = %w(public audit)
end
config/initializers/assets.rb
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )
Rails.application.config.assets.precompile += %w( *.js *.png *.eot *.woff *.ttf *.svg *.gif)
config/environments/includes/s3_assets.rb
def configure_s3_assets(config)
# Do not compress assets
config.assets.compress = false
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Generate digests for assets URLs
config.assets.digest = true
config.assets.enabled = true
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += %w(
)
# find javascripts/ stylesheets/ -type f | sed 's/\.scss//' | sed 's/\.coffee//' |
# sed 's/^.*\/\///'| sort
# defaults to application.js, application.css
# application.css has home.css ?
config.assets.precompile += %w(
handlebars.js
jquery-1.7.js
json2.js
)
end
After digging around in the sprockets code, I discovered that my list of resolvers was empty. I'm not sure what was missing from my configuration, but I fixed the problem by adding the following to config/application.rb
config.assets.resolve_with = [:manifest] // in production
config.assets.resolve_with = [:manifest, :environment] // in development

Extra directory prepended to my routes in production

My rails application works fine locally, and seems to deploy normally. The root route brings you to my welcome splash page. I have a link on that page to the index for my organizations model, generated by the following code:
<%= link_to("Organizations", organizations_path, :class => "button_blue") %>
When I try to click that link on the production server, hosted by a2 hosting, I get the following error:
Started GET "/database/organizations.shtml" for 11.222.33.444 at Sat Oct 05 00:10:35 -0400 2013
ActionController::RoutingError (No route matches [GET] "/database/organizations.shtml"):
actionpack (3.2.13) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
...
Why is it trying to get "/database/organizations" instead of "/organizations" like it does in development? The url in the address bar reads "http://database.mysite.com/organizations". Does it have something to do with the fact that the site is located at the subdomain database.mysite.com? How do I get around this, since I can't use the primary domain for my rails app?
For what it's worth, here's what I get when I run
RAILS_ENV=production bundle exec rake routes | grep organization
on the server:
organizations GET /organizations(.:format) organizations#index
POST /organizations(.:format) organizations#create
new_organization GET /organizations/new(.:format) organizations#new
edit_organization GET /organizations/:id/edit(.:format) organizations#edit
organization GET /organizations/:id(.:format) organizations#show
PUT /organizations/:id(.:format) organizations#update
DELETE /organizations/:id(.:format) organizations#destroy
Here is my routes.rb:
MyApp::Application.routes.draw do
root :to => 'application#index'
resources :grantmakers, :grant_records, :events, :organizations
end
Here is my config/environments/production.rb:
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# 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 = true
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
end
And here is my application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
def index
end
before_filter :basic_http_authentication
private
def basic_http_authentication
if Rails.env.production?
authenticate_or_request_with_http_basic do |username, password|
username == '---' && password == '---'
end
end
end
end
Thanks very much for your help.
Thanks to #phoet, I finally identified the problem and found a solution.
My Apache server was rewriting the URLs for some reason that I still don't understand. I think it might have to do with the way A2 hosting allows you to set up subdomains. In any case, adding the following line to the end of the .htaccess file in the subdomain's root directory solved the problem:
RewriteEngine Off
This simply disables all rewriting: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteengine

Rails ignoring precompiled assets in S3, "could not find file 'bootstrap'"

I'm precompiling assets locally and pushing them to S3. In production I get this error:
heroku[router]: at=info method=GET path=/ host=www.someapp.org fwd="76.87.106.226" dyno=web.1 connect=2ms service=614ms status=500 bytes=0
app[web.1]: ActionView::Template::Error (couldn't find file 'bootstrap'
app[web.1]: app/views/application/_stylesheets.html.erb:1:in `...'
app[web.1]: app/views/layouts/application.html.erb:5:in `...'
app[web.1]:
app[web.1]: (in /app/app/assets/stylesheets/application.css:11)):
app[web.1]: 1: <%= stylesheet_link_tag "application", media: "all" %>
When I run in production mode locally I do not get that error.
Here is my application.rb:
require File.expand_path("../boot", __FILE__)
# Pick the frameworks you want:
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module SomeApp
class Application < Rails::Application
require "ksp"
require "markdowner"
require "patches/carrier_wave"
VERSION = "1.0.0"
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = "Central Time (US & Canada)"
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join("my", "locales", "*.{rb,yml}").to_s]
# config.i18n.default_locale = :de
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
# Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true
# Use SQL instead of Active Record"s schema dumper when creating the database.
# This is necessary if your schema can"t be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = "1.0"
config.generators do |generator|
generator.test_framework :rspec, view_specs: false
end
config.assets.prefix = "/assets/#{Rails.env}"
config.filepicker_rails.api_key = ENV["FILEPICKER_API_KEY"]
# Allow for CORS requests
config.middleware.use Rack::Cors do
allow do
origins "*"
resource "*", headers: :any, methods: [:get, :post, :options]
end
end
end
end
Here is my production.rb:
SomeApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# 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
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
config.cache_store = :dalli_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
config.action_controller.asset_host = "d20eprk8nbwd96.cloudfront.net"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
config.action_mailer.default_url_options = { host: "www.someapp.org" }
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
end
Here is my asset_sync.rb:
if defined?(AssetSync) && !(ENV["HOME"] == "/app")
AssetSync.configure do |config|
config.fog_provider = "AWS"
config.fog_directory = ENV["AMAZON_BUCKET"]
config.aws_access_key_id = ENV["AMAZON_S3_KEY"]
config.aws_secret_access_key = ENV["AMAZON_S3_SECRET"]
# Increase upload performance by configuring your region
config.fog_region = "us-west-2"
#
# Don't delete files from the store
config.existing_remote_files = ENV["ASSET_SYNC_EXISTING_REMOTE_FILES"]
#
# Automatically replace files with their equivalent gzip compressed version
config.gzip_compression = ENV["ASSET_SYNC_GZIP_COMPRESSION"]
#
# Use the Rails generated 'manifest.yml' file to produce the list of files to
# upload instead of searching the assets directory.
config.manifest = ENV["ASSET_SYNC_MANIFEST"]
#
# Fail silently. Useful for environments such as Heroku
# config.fail_silently = true
end
end
Here is my application.css:
/*
*= require bootstrap
*= require bootstrap-responsive
*= require font-awesome
*= require chosen
*= require bootstrap/tour
*= require bootstrap/lightbox
*= require_self
*/
In production mode locally the method gives me the correct cloudfront URL.
What's going wrong here?
Turns out despite precompiling locally, Heroku was still trying to precompile on Heroku.
It would fail, and then try to compile the assets live. This would then fail in the way described.
I solved this by creating an empty file /public/assets/manifest.yml, even though my config says assets are in /public/assets/production/

Caching caches_action fragmens in Memcache and assets in the file system

Using Rails 3.1.1 on Heroku, Dalli gem and Memcachier.
I am trying to troubleshoot an issue where keys disappear from Memcachier, in order to do this I would like to make sure that only the content from my caches_action will be cached in the memcache. I would like my assets (jpg's etc) to be cached elsewhere.
I believe it is the same issue as this question but when I do the same, i.e. adding
config.action_dispatch.rack_cache = {
:metastore => Dalli::Client.new,
:entitystore => 'file:tmp/cache/rack/body',
:allow_reload => false
}
to my production.rb, it doesn't really seem to do anything.
My production.rb in full:
MyDemoApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = true
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
# Specifies 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
config.cache_store = :dalli_store
config.action_dispatch.rack_cache = {
:metastore => Dalli::Client.new,
:entitystore => 'file:tmp/cache/rack/body',
:allow_reload => false
}
# Set expire header of 30 days for static files
config.static_cache_control = "public, max-age=2592000"
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
end
Caching assets work fine (get cache fresh-responses) and caching actions like this:
caches_action :show, :layout => false, :expires_in => 3.days
Also creates a cached entry in Rails cache (although they disappear after a while).
My question now is: How can I, if possible, do so that only my caches_action fragments end up in my Memcache (and not my assets)?
A bonus question would be, do you see anything out of the ordinary in my production.rb?
I use the gem 'asset_sync' to move all my assets out to Amamzon S3
See Instructions here
You get three advantages:
Your assets are served from Amazon so the page loads faster for the
user
Your slug size on Heroku is smaller and is supposed to be more
performant
Your assets will no longer be in memecahce
All my assets cost me about 20cents every three month to host on Amamzon

Rails loads css files from public/assets instead of app/assets in development mode

I'm running in development mode. I'm editing .css files but not seeing changes. If I go to public/assets/ and rename application.css, I see changes (it can't find any styles). Why would it be using that file? Isn't that for production mode? I don't want to pre-compile all the time in dev mode. thanks. Environment files added below.
development.rb :
Tcms::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
end
production.rb :
Tcms::Application.configure do
# Uncomment and set this to match your production URL. Used for emailing links to the CMS. (default: localhost:3000)
# config.cms.site_domain = "www.example.com"
# Configure your mail server's address below
config.action_mailer.smtp_settings = {:address => 'mail.yourmailserver.com', :domain => config.cms.site_domain}
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = true
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies 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
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
config.log_level = :info
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
end
As default, Rails will serve assets within /public and not compiling live, if these assets exists.
To get rid of it, either delete the assets within the public dir,
or add the following line into you config/environments/development.rb
config.serve_static_assets = false
config.serve_static_assets configures Rails itself to serve static
assets. Defaults to true
More to read: here
What version of rails are you running? Is this an app that upgraded from 2.x or 3.0.x to 3.1 or 3.2? This almost sounds like this app was pre-asset pipline. Here is a good tutorial on upgrading from pre-asset pipline to asset-pipline...
http://railscasts.com/episodes/282-upgrading-to-rails-3-1
...also here is a good basic tutorial for asset pipeline...
http://railscasts.com/episodes/279-understanding-the-asset-pipeline

Resources