Permission denied for a css when deploying to heroku - ruby-on-rails-3

I have a sample app that is using compass gem including blueprint. I just deployed this app on heroku for the first time and I'm seeing the following error in heroku logs
Errno::EACCES (Permission denied - /app/public/stylesheets/ie.css):
Is there something special required in my rails app that will make this error go away? I'm assuming it's coming because I'm using the compass gem...

Do a compass compile before deploying to heroku.
Also, in your production.rb, add the following line:
Sass::Plugin.options[:never_update] = true
This will prevent compass from compiling css at runtime (since heroku does not allow writes on filesystem)

Just set this option to true in config/environments/production.rb and everything will work fine:
config.assets.compile = true

Save ie.css from your local machine, add it into your public/stylesheets folder, and push it up to heroku.

Related

Rails 3 Development Asset Pipeline Directs to Public Folder

I just pulled down two new rails 3.2.6 projects that I have designated for some clean up. While attempting to make some UI changes I realized that even in development the asset pipeline was routing towards the public/assets folder.
After making some changes to the scss, I ran rake assets:clean followed by rake assets:precompile. Both ran without error and I restarted my localhost, and the styling was broken.
I've walked through the rails asset pipeline guide, as well as some other documentation that hasn't really provided the answer I need.
I attempted adding config.serve_static_assets = falseto the development.rb file in the config folder, however this as well did not render any scss.
Can anyone explain what is happening, and the best method of resolution?
Thanks
Add below statement to development.rb to prevent loading of files from public/assets.
config.serve_static_assets = false
Now restart the server, You will get better view.
To precomple the code in Test mode. -
Add this configuration to test.rb
config.assets.compile = false
config.serve_static_assets = true

Rails App doesn't work on production enviroment

I have a rails app set up with Nginx + Passenger. When i have rails_env development; on my nginx.conf everything works fine, but when I remove it so the app get server on production env it just doesnt work, seems like its not loading gems or something. Feel free to take a look at the errors here www.luisurraca.co.cc
error message:
undefined method `has_attached_file' for #<Class:0x00000003b0be10>
Exception class:
NoMethodError
Right now its referring to the paperclip gem, but if i start removing gems from the gemfile it will display error from some other gem and so on.
Any ideas what the issue might be?
You probably defined paperclip/whatever in development group and it is not installed with bundle install --deployment. To see installed gems do bundle show not gem list.
did you specify ruby path for nginx? it should look like this:
http {
passenger_root /home/rlisowski/.rvm/gems/ruby-1.9.3-p194/gems/passenger-3.0.13;
passenger_ruby /home/rlisowski/.rvm/wrappers/ruby-1.9.3-p194/ruby;
# ....

How can I run SOME initializers when doing a Rails assets:precompile?

Background
I have an app that I recently updated to Rails 3.2.1 (from Rails 3.0.x) and have refactored the JS and CSS assets to make use of the new asset pipeline. The app is hosted on Heroku with the Celadon Cedar stack.
App Config
I keep application specific configuration in a YAML file called app_config.yml and load it into a global APP_CONFIG variable using an initializer:
# config/initializers/load_app_config.rb
app_config_contents = YAML.load_file("#{Rails.root.to_s}/config/app_config.yml")
app_config_contents["default"] ||= {}
APP_CONFIG = app_config_contents["default"].merge(
app_config_contents[Rails.env] || {} ).symbolize_keys
Asset Compilation on Heroku
Heroku has support for the Rails asset pipeline built into the Cedar stack. When you push an app to Heroku it automatically calls rake assets:precompile on the server as a step in the deploy process. However it does this in a sandboxed environment without database access or normal ENV vars.
If the application is allowed to initialize normally during asset precompilation an error is thrown trying to connect to the database. This is easily solved by adding the following to the application.rb file:
# Do not load entire app when precompiling assets
config.assets.initialize_on_precompile = false
My Problem
When initialize_on_precompile = false is set, none of the initializers in config/initializers/* are run. The problem I am running into is that I need the APP_CONFIG variable to be available during asset precompilation.
How can I get load_app_config.rb to be loaded during asset compilation without initializing the entire app? Can I do something with the group parameter passed to Rails::Application.initialize! ?
Rails lets you register initializers only in certain groups, but you need to use the Railtie API:
# in config/application.rb
module AssetsInitializers
class Railtie < Rails::Railtie
initializer "assets_initializers.initialize_rails",
:group => :assets do |app|
require "#{Rails.root}/config/initializers/load_config.rb"
end
end
end
You don't need to check if AppConfig is defined since this will only run in the assets group.
And you can (and should) continue to use initialize_on_precompile = false. The load_config.rb initializer will be run when initializing the app (since it's in config/initializers) and when pre-compiling without initializing (because of the above code).
Definitely check out asset_sync on github. Or our Heroku dev centre article on Using a CDN asset Host with Rails 3.1 on Heroku.
The issues with environment variables have recently been solved by a Heroku labs plugin, that makes your application's heroku config variables accessible during compilation time. To enable this, read about the user_env_compile plugin.
Also. There is quite a big performance improvement in using asset_sync vs letting your application lazily compile assets in production or serving them precompiled directly off your app servers. However I would say that. I wrote it.
With asset_sync and S3 you can precompile assets meaning all the assets are there ready to be served on the asset host / CDN immediately
You can only require the :assets bundle in application.rb on precompile, saving memory in production
Your app servers are NEVER hit for asset requests. You can spend expensive compute time on, you know. Computing.
Best practice HTTP cache headers are all set by default
You can enable automatic gzip compression with one extra config
Here's what I came up with. In the assets that need app configuration, I place this line at the very beginning:
<% require "#{Rails.root}/config/initializers/load_config.rb" unless defined?(AppConfig) %>
... and add .erb to the file name, so that video_player.js.coffee becomes video_player.js.coffee.erb. Then I can safely use AppConfig['somekey'] afterwards.
During the asset pre-compilation, it loads app config despite the initialize_on_precompile set to false, and does it only once (which avoids constant redefinition issues).
Yes, it's a kludge, but many times nicer than embedding configs in asset files.
For Heroku I am running the Asset Sync gem to store my files on a CDN to avoid hitting Heroku for static images. It works nicely. I also have initialize on precompile false, but the Asset Sync runs it's own initializer so you could put your code in that. https://github.com/rumblelabs/asset_sync
Although your intializer is not run when the assets are precompiling, you should still find that they run as Rails boors up as normal, however, this will be on the first hit to the application rather than at the deploy step.
I'm not entirely sure what the issue you're having is, but if you follow the Rails conventions the deploy will work as expected.

Rails 3 - Error after deploying to Heroku

I have an application working in localhost and also heroku. The last time that I pushed the new version to heroku I got an error during heroku db:migrate and did heroku db:push and everything was ok.
I get the following error when executing the App.
/app/.bundle/gems/ruby/1.9.1/gems/aws-s3-0.6.2/lib/aws/s3/extensions.rb:206:in `const_missing_from_s3_library': uninitialized constant AnswersController::Authentication (NameError)
Here is the relevant code
class AnswersController < ApplicationController
include Authentication
...
Authentication is a module defined in lib:
# encoding: utf-8
require 'base64'
require 'openssl'
module Authentication
...
It is working in localhost but not in heroku.
Any help??
Thanks
Try adding the lib folder to your the config.auto_load path in application.rb
config.autoload_paths += %W(#{config.root}/lib)
Also, take a look at this link.

Using Compass on Heroku: /tmp for stylesheets remotely and locally

I'm currently using Compass with Heroku using this configuration recommended on the Heroku knowledge base. Heroku has a read-only file system, and so the compiled stylesheets need to be stored in /tmp. This works fine remotely on Heroku; locally, however, Rails expects to find stylesheets in /public/stylesheets (when called through = stylesheet_link_tag 'screen.css', :media => 'screen, projection').
In order to solve the problem, I have created symbolic links in /public/stylesheets using ln -s tmp/stylesheets/screen.css public/stylesheets/screen.css and that seems to work.
Is there a way to solve this problem without using symbolic links, perhaps by changing some configuration in Rails? I've poked around without much success.
Here is my config/initializers/compass.rb:
require 'compass'
require 'compass/app_integration/rails'
Compass::AppIntegration::Rails.initialize!
# Required for Heroku:
require 'fileutils'
FileUtils.mkdir_p(Rails.root.join("tmp", "stylesheets"))
Compass::AppIntegration::Rails.initialize!
Rails.configuration.middleware.delete('Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
:urls => ['/stylesheets'],
:root => "#{Rails.root}/tmp")
And here is my config/compass.rb:
project_type = :rails
project_path = Compass::AppIntegration::Rails.root
# Set this to the root of your project when deployed:
http_path = "/"
# Necessary for Heroku (original commented out:
css_dir = 'tmp/stylesheets'
#css_dir = "public/stylesheets/compiled"
sass_dir = 'app/views/stylesheets'
environment = Compass::AppIntegration::Rails.env
Any help would be greatly appreciated.
I was actually just about to set up Compass with our Rails application, which is hosted on Heroku, so cheers for giving me an excuse to work through this. :)
The answer is simple:
Modify 'config/compass.rb':
project_type = :rails
project_path = Compass::AppIntegration::Rails.root
http_path = "/"
environment = Compass::AppIntegration::Rails.env
if environment == 'production'
css_dir = "tmp/stylesheets"
sass_dir = "app/views/stylesheets"
else
css_dir = "public/stylesheets"
sass_dir = "app/stylesheets"
end
Then modify 'config/initializers/compass.rb':
require 'compass'
require 'compass/app_integration/rails'
Compass::AppIntegration::Rails.initialize!
require 'fileutils'
FileUtils.mkdir_p(Rails.root.join("tmp", "stylesheets"))
environment = Compass::AppIntegration::Rails.env
if environment == 'production'
Compass::AppIntegration::Rails.initialize!
Rails.configuration.middleware.delete('Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
:urls => ['/stylesheets'],
:root => "#{Rails.root}/tmp")
end
... and voila, you're good.
ok, I'm a big heroku and compass fan myself so i've been through this many times
Heroku's docs, whilst giving correct information, provide poor advice in this instance.
When using compass, the best thing to do, 99.999% of the time is turn it off in production mode.
This means that you compile your stylesheets on your development machine and then add them to your git repo before pushing to heroku.
You will suffer a reasonably sizeable performance hit if you allow compass to compile on the server.
So here's what I do:
You should have a config.ru file at the base of your app. Open it and add the following:
require 'sass/plugin/rack'
use Sass::Plugin::Rack
Sass::Plugin.options[:never_update] = true
You can then remove quite a lot of the code from your initializer (especially the part where you unload Sass::Plugin::Rack). Additionally you will want to remove the if statement from compass.rb in config folder
Think about it, why would you want Sass to compile a stylesheet on the server? It just eats up processing power. Hope this helps,
EDIT::
PS - I should add that you will need to run compass watch from the command line now in order to get your stylesheets to compile in your dev environment
The recommended Heroku configuration will also work locally.
Removed the second 'Compass::AppIntegration::Rails.initialize!' from config/initializers/compass.rb, you only need it once.
Ensure your scss files are in 'app/views/stylesheets'
On both local and production servers the stylesheets will be compiled to tmp/stylesheets, and a request to /stylesheets will resolve to tmp/stylesheest. No need for two separate configurations.