serving static files with Ruby Espresso - ruby

I'm trying to serve some assets using the el gem but can't seem to get it to work. I've referred to another question posted here -- Assets in espresso breaks my app
My setup looks like this --
require 'e'
require 'el'
...
app = E.new(true){
assets_url '/pub', true
}
But hitting localhost:5252/pub/hello.txt (yes, this file exists) results in 404. What am I missing?

You missed to append any paths to Sprockets environment.
http://espresso.github.io/Periphery/Assets.html#sprockets
Please try:
app = E.new(true){
assets_url '/pub', true
assets.append_path 'relative-path-to-static-files'
}

Related

ckeditor.js file can't be found by rails_admin

I am trying to use ckeditor (4.0.6) with Using rails_admin (0.5.0) in Rails 4.0 on DigitalOcean server.
I have included it in the rails_admin.rb initializer as follows and it works in production mode on my local
config.model Faq do
field :display_order
field :question
field :answer, :ck_editor
end
However on DigitalOcean when I go into Rails_Admin and try to make a new FAQ object it won't load ckeditor because it can't find the js.
http://dummy.com/assets/ckeditor/ckeditor.js?_=1381313244552 404 (Not Found)
rails_admin-5daa9b7b76a226bdfa46a07fdaf2d77d.js:3
How can I fix this?
The problem is because Rails assets compile actually added a fingerprint on to the assets file of every CKeditor file, while the rails-admin is looking for a non fingerprint version of the file.
This issue only happens in the rails 4 with ckeditor. Actually the Readme.md of the ckeditor gem did mention about the issue and how to resolve it, but it isn't complete.
To resolve you could write a rake file to remove all the fingerprints and run this during deployment.
Here is my solution to resolve this issue.
Create a rake file in lib/tasks/ckeditor.rake with the following code
namespace :ckeditor do
desc 'Create nondigest versions of some ckeditor assets (e.g. moono skin png)'
task :create_nondigest_assets do
fingerprint = /\-[0-9a-f]{32}\./
for file in Dir[File.join('public/assets/ckeditor', '**', '*.js'),
File.join('public/assets/ckeditor', '**', '*.js.gz'),
File.join('public/assets/ckeditor', '**', '*.css'),
File.join('public/assets/ckeditor', '**', '*.png'),
File.join('public/assets/ckeditor', '**', '*.gif')]
next unless file =~ fingerprint
nondigest = file.sub fingerprint, '.' # contents-0d8ffa186a00f5063461bc0ba0d96087.css => contents.css
FileUtils.cp file, nondigest, verbose: true
end
end
end
For Capistrano user, make sure you include this in your deploy.rb
desc 'copy ckeditor nondigest assets'
task :copy_nondigest_assets, roles: :app do
run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} ckeditor:create_nondigest_assets"
end
after 'deploy:assets:precompile', 'copy_nondigest_assets'
For Heroku user, you would need to run the rake file manually each time before you check in your code. Make sure you do your rake assets:precompile before this.
rake ckeditor:create_nondigest_assets
Hope it helps
I don't know, have you precompiled your assets?
If you're switching from a different kind of host, like Heroku, you
may forget that you have to manually precompile your assets. You're
lucky, though – it's easy!
RAILS_ENV=production rake assets:precompile If you run into problems,
try running this instead:
RAILS_ENV=production rake assets:precompile:primary
From https://www.digitalocean.com/community/articles/how-to-launch-your-ruby-on-rails-app-with-the-digitalocean-one-click-image

Rails 4, Heroku doesn't recognize precompiled manifest-(fingerprint).json

After upgrading to Rails 4, public/assets/manifest.yml is not generated anymore. Instead the different formatted manifest-(fingerprint).json is present.
But it seems to me that the server is still looking for the old manifest.yml format, ignoring the .json version?
I see other questions based on similar problems, but they seems to be sovled by upgrading to Rails 4, adding rails_12factor to gem file, setting serve_static_assets = true, etc., but none of these solutions seems to have any effect in my scenario.
I am tired and uninspired due to this annoying problem, any help will be appreciated!
Logfile from Heroku:
ActionController::RoutingError (No route matches [GET] "/assets/layouts/test/test.html"):
Gemfile:
ruby '2.0.0'
gem 'rails', '4.0.0'
...
gem "compass-rails", github: "milgner/compass-rails", ref: "1749c06f15dc4b058427e7969810457213647fb8"
...
gem 'rails_12factor', group: :production
production.rb
RailsFoundationAngular::Application.configure do
config.assets.initialize_on_precompile = false
config.cache_classes = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_assets = true
config.assets.compress = true
config.assets.compile = false
config.assets.digest = true
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.action_dispatch.x_sendfile_header = nil
end
I am using Angular and their ui-router, and this is the part of my routes.js.coffee where the test.html is linked:
.state "root",
url: "/"
views:
"root":
controller: "ApplicationController"
templateUrl: "/assets/layouts/test/test.html"
I have also tried precompiling locally, but as I am using Rails 4 here as well, still no manifest.yml is created, only the .json version.
Of course, everything is working just perfectly in development...
So my actual cuestion:
How do I make Heroku recognize and use the manifest-(fingerprint).json -file, or alternative ways to make this work?
The answer is, that Heroku already does recognize and use the manifest-(fingerprint).json -file. The "workaround" in my comment above, is the proper way to reference these files, and by doing so, the manifest-file is used the way it's ment to be used.
Renaming the file with the internal link to .erb, and referencing like this: templateUrl: "<%= asset_path('layouts/test/test.html') %>" does the trick. All internal files, images, and html -files should be referenced like this.
It's all described very thoroughly here: Asset-pipeline guide
It seems so simple and straightforward now, but I really spent a lot of time trying to get the wrong way around this from the beginning.
I hope this answer can save the time for someone else.

Heroku does NOT compile files under assets pipelines in Rails 4

Everything goes well in local machine with assets pipeline in Rails 4 and Ruby 2.0. But when deploying to heroku, it is shown that:
-----> Preparing app for Rails asset pipeline
Running: rake assets:precompile
I, [2013-03-12T03:28:29.908234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/rails-2ee5a98f26fbf8c6c461127da73c47eb.png
I, [2013-03-12T03:28:29.914096 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/trash-3c3c2861eca3747315d712bcfc182902.png
I, [2013-03-12T03:28:33.963234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-bf2525bd32aa2a7068dbcfaa591b3874.js
I, [2013-03-12T03:28:40.362850 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-13374a65f29a3b4cea6f8da2816ce7ff.css
Asset precompilation completed (14.36s)
Heroku seems to compile files but put it in /tmp without any errors. My questions are:
How come Heroku compile assets files to /tmp?
My last solution was to run RAILS_ENV=production bundle exec rake assets:precompile locally, but this generated a manifest-xxxxxx.json in public/assets, rather than manifest.yml, so that heroku doesn't detect the JSON manifest file. I sorted it out by manually created a yml from the json file and heroku became happy. Has heroku's approach been outdated?
Heroku's asset plugins no longer work since Rails 4 does not support plugins. You need to use Heroku's asset gems instead. Place this in your Gemfile:
group :production do
gem 'rails_log_stdout', github: 'heroku/rails_log_stdout'
gem 'rails3_serve_static_assets', github: 'heroku/rails3_serve_static_assets'
end
Follow Heroku's guide on getting started with Rails 4.
Update (07/22/2013): Heroku now supplies a different gem to precompile assets.
group :production do
gem 'rails_12factor'
end
You need to config Rails to serve static assets in production: config/environments/production.rb
SampleApp::Application.configure do
.
.
.
config.serve_static_assets = true
.
.
.
end
UPDATE:
In Rails 4 is deprecated, and has been changed by:
config.serve_static_files = true
Since rails 4 replaced manifest.yml with manifest-(fingerprint).json, you'll want to enable static asset serving.
From Getting Started with Rails 4.x on Heroku:
gem 'rails_12factor', group: :production
then
bundle install
and, finally,
git push heroku
Fixed the issue for me. Hope this helps!
I run exactly into the same problem.
I set config.serve_static_assets = true in my environments/production.rb file until heroku wont't support the new manifest format.
So it is a temporal solution until heroku support will be added.
After hours of googling in which none of the guides on Heroku or the suggestions on StackOverFlow helped me, I finally ran into this blog post which offered this clue:
heroku labs:enable user-env-compile --app=YOUR_APP
Without this, the asset pipeline will always try to init the whole app and connect to the database (despite all the things you may have read that rails 4 now longer does this). This exposes your Heroku configuration to Rails so it can boot up successfully and run rake tasks like assets:precompile.
I needed to use this gem:
gem 'rails_12factor', group: :production #need this for rails 4 assets on heroku
And in /config/environments/production.rb I needed to set:
config.assets.compile = true
My understanding is that the rails_12_factor gem sets config.serve_static_assets = true, amongst other things.
In my case, assets compiled following the instructions above but it wasn't picking the bootstrap glyphicons 'fontawesome-webfont' so this worked for me finally after wasting so many hours researching.
Gem file
gem 'rails_12factor', group: :production
bundle install
config/application.rb
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif,
"fontawesome-webfont.ttf",
"fontawesome-webfont.eot",
"fontawesome-webfont.svg",
"fontawesome-webfont.woff")
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
environment/production.rb
config.serve_static_assets = true
Then finally, I ran
rake assets:precompile RAILS_ENV=production and pushed it to heroku and that worked.
This was an issue with the Heroku Ruby Buildpack, but an update was deployed today (2013-05-21). Please try it out and let us know.
To answer your questions:
#1) This is sprockets output; things are compiled to /tmp and then moved (See here in Sprockets). To my knowledge this has always been done this way, but it wasn't until Sprockets version was updated in Rails that we got this new debug-type output.
#2) Previously assets:precompile genereated a manifest.json file, but now in Rails 4 the manifest file has a fingerprint in it, which wasn't detected previously. This was fixed with #74.
I added this to the top of one of my css.scss files in the assets/stylesheets/ folder.
#import "font-awesome";
then ran..
rake assets:clean
and...
rake assets:precompile RAILS_ENV=production
In Rails 4.2.4 your production.rb has the line:
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
That means, gem 'rails_12factor', group: :production doesn`t need to change it to true, as it can be set through the heroku environment variables. You also will get a warning if you remove the rails_12factor gem.
If you have problems with assets, login to the heroku console heroku run rails console and find out the asset path for a file puts helper.asset_path("application.js") .
One strange behaviour I noticed between development and production, when the file ending is not provided:
With a image /assets/images/image_01.jpg the following output from asset_pathsdiffers:
Development:
development > puts helper.asset_path('profile_01')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
Production:
development > puts helper.asset_path('profile_01')
=> /profile_01
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
You do not have to run RAILS_ENV=production rake assets:precompile, heroku does this for you during deploy. Also you do not have to precompile the assets in development and push them to heroku.
Apart from ensuring you have the 'rails_12factor' gem installed the only thing you need to do is this.
# config/application.rb
config.assets.paths << Rails.root.join('vendor', 'assets')
It seems that although Rails knows exactly what it wants, Heroku needs reminding to include the assets folder as part of the assets paths.
Use Image Extensions
I had this same issue, but for a different reason.
Instead of
<%= asset_path 'facebook-link' %>
Use:
<%= asset_path 'facebook-link.png' %>
While the first one worked locally, when I pushed to Heroku my images were breaking and I had no clue why. Using the full file extension fixed the problem :)
Add this gem gem 'rails_serve_static_assets'
https://github.com/heroku/rails_serve_static_assets
If you are using controller specific assets as in:
<%= javascript_include_tag params[:controller] %> or <%= javascript_include_tag params[:controller] %>
Then in production you will need to explicitly precompile those (in development rails compiles files on the fly).
See official Rails guide here: http://guides.rubyonrails.org/asset_pipeline.html#controller-specific-assets
To precompile as explained in the guides (here: http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets) you will need to add the following to the config/application.rb
# config/application.rb
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
I figure I'll add this as an answer since this question is linked from the Heroku Support page if you search for "assets".
This is mostly for people who are updating their app to Rails 4, but after going through this - and many other SO posts - what finally got me was changing the following in production.rb:
config.action_dispatch.x_sendfile_header = "X-Sendfile"
To:
config.action_dispatch.x_sendfile_header = nil
I hadn't caught this when I upgraded and as usual this took me forever to figure out. Hopefully it helps someone else! Shout out to PatrickEm who asked/answered the same in his question.
This may not answer the original question's root cause, But I was having a similar symptom with a different root cause.
Pre-compilation of a JPEG files changes the file extension to JPG, meaning that asset_path("my_image.jpeg") and asset_path("my_image") didn't work. Remove the "e" from JPEG and voila, it works.
Others have described the same problem here https://blazarblogs.wordpress.com/2016/04/06/rails-force-to-precompile-jpeg-to-jpg/
Is this a bug? Or desired behaviour? And also weird that it only doesn't work in my Heroku-hosted production environment. Maybe they have some sort of configuration.

no route matches for assets/images in Rails

Working on rails, images are not visible and giving error.
Started GET "/assets/home.png" for 127.0.0.1 at 2012-06-19 12:23:24 +0530
Served asset /home.png - 404 Not Found (24ms)
ActionController::RoutingError (No route matches [GET] "/assets/home.png"):
I have used command
rake assets:precompile
production.rb
config.assets.compress = true
config.assets.compile = false
application.rb
config.assets.enabled = true
config.assets.version = '1.0'
Thanks for any help!
Actually you cannot reference your image with /assets/home.png path.
It will work in development mode, but in production all of your assets have a fingerprint in their filename (read this http://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark)
That's why, in assets-pipeline enabled applications you need to reference all of your assets using helper methods. Read this doc to learn about the different helpers available in Ruby, JS and Sass files: http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
The lack of a fingerprint in the file request suggests that you are running this in development. I am also going to guess that this is an app upgraded from an older version of Rails.
Any images need to be in the folder /assets/images for the pipeline to work.
Also, you do not need to precompile when in development mode.
Delete the public/assets folder, delete the folder tmp/cache/assets, and restart your server.
If this images are in the correct location, it should work.

Broken precompiled assets in Rails 3.1 when deploying to a sub-URI

I'm in the process of updating a Rails 3 app to use Rails 3.1 and as part of that, am making use of the new asset pipeline. So far, I've got everything working apart from one rather annoying problem I can't solve.
The application and all its assets works fine in development, but in production it is deployed to a sub-URI using Passenger (http://the-host/sub-uri/). The problem with this is that the assets are pre-compiled during deployment and one of my CSS (well, it's a .css.scss file) files is making use of the image-url helper from the sass-rails gem. Since during the pre-compilation process, the paths are hard-coded into the precompiled CSS file, the sub-uri is not taken account of:
In my .css.scss file:
body { background-image: image-url("bg.png"); }
The result in the compiled application-<md5-hash-here>.css file:
body { background-image: url(/assets/bg.png); }
What it should be to make it work correctly:
body { background-image: url(/sub-uri/assets/bg.png); }
Is this scenario just asking too much? If so, I'll have to switch back to the old non-asset-pipelined way and just serve my images and CSS from public. However it seems like something which should have been thought about and solved...? Am I missing the solution?
Edit 1: I should note that using the erb solution instead yields the same result, as one would expect.
Edit 2: in response to Benoit Garret's comment
No, the problem isn't related to the config.assets.prefix. I tried setting that (to /sub-uri/assets rather than the default of /assets) but it turned out that was the wrong thing to do - it seems like this setting is already in relation to the root of the Rails app, not the server. Removing that (and thus returning to the default) has fixed all the weird issues that caused (and there were many, all the assets ended up in /sub-uri/sub-uri/assets - it was all very strange). The only problem is that the image-url helper and friends do not pick up the sub-URI when they are pre-compiled. Needless to say, this is logical since when it is pre-compiled, it couldn't possibly know that when it's running under Passenger, it'll be configured in this way. My question is how to inform it of this and thus end up with the correct paths in the precompiled result. If indeed it can be done.
My current workaround is to reference the iamge in the CSS like this: url(../images/bg.png) and place it in the non-pipelined public/images location. Hardly ideal since it doesn't benefit from the fingerprinting and everything which the pipeline provides.
Finally I've worked out a couple of workarounds/solutions.
1) From https://github.com/rails/sass-rails/issues/17 it looks like this could get fixed in sass-rails. I've monkey-patched helpers.rb myself along the lines of the proposed patch in the link above. I simply set the required environment variable in the asset precompile line in deploy.rb.
I do all my monkey patching in a single file config/initializers/gem_patches.rb. In this file I patched this method as:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
path = options[:custom][:resolver].public_path(asset, kind.pluralize)
path = ENV['PRODUCTION_URI'] + path if ENV['PRODUCTION_URI']
path
end
end
end
end
2) Alternatively if you are ok to embed images in the CSS, changing the stylesheet to have a .erb extension, and replacing the image-url("bg.png") with url(<%= asset_data_uri "bg.png" %>) will work without any need to change sass-rails. asset-data-uri doesn't exist as a pure Sass function so you have to use the Rails helper asset_data_uri.
In the latest Rails 3.1.3 you need to monkey patch a different module now, for it to work
This is what I did
module Sprockets
module Helpers
module RailsHelper
def asset_path(source, options = {})
source = source.logical_path if source.respond_to?(:logical_path)
path = asset_paths.compute_public_path(source, asset_prefix, options.merge(:body => true))
path = options[:body] ? "#{path}?body=1" : path
if !asset_paths.send(:has_request?)
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path if ENV['RAILS_RELATIVE_URL_ROOT']
end
path
end
end
end
end
And in my deploy.rb I have:
desc "precompile the assets"
namespace :assets do
task :precompile_assets do
run "cd #{release_path} && rm -rf public/assets/* && RAILS_ENV=production bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT='/my_sub_uri'"
end
end
before "deploy:symlink", "assets:precompile_assets"
I'm using Rails 3.1.3 and deploying to a sub-URI successfully.
I have NOT monkey-patched anything.
The key problems with this setup have been better discussed here. As you can see, the solution was applied to Rails 3.2 and never backPorted to 3.1.4.
But, I have came to a solution using Rails 3.1.3 that works for my setup.
Try this: (I'm no expert, just trying to contribute to solve a problem that hassled me for hours...)
environment.rb:
#at top:
ENV['RAILS_RELATIVE_URL_ROOT'] = '/rais'
production.rb:
config.assets.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] ? ENV['RAILS_RELATIVE_URL_ROOT'] + '/assets' : '/assets'
routes.rb:
Rais::Application.routes.draw do
scope ENV['RAILS_RELATIVE_URL_ROOT'] || '/' do #see config/environment.rb
<<resources here>>
end
end
As you can see, I've put assets.prefix inside production.rb, not in application.rb
After that you do:
rake assets:clear
rake assets:precompile
and than, test with the console:
RAILS_ENV=production rails console
Results:
foo = ActionView::Base.new
foo.stylesheet_link_tag 'application'
=> "<link href=\"/rais/assets/layout.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/rais/assets/application.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />"
foo.image_tag('arrow-up.png')
=> "<img alt=\"Arrow-up\" src=\"/rais/assets/arrow-up-ca314ad9b991768ad2b9dcbeeb8760de.png\" />"
After a bit of digging around, I have found the issue. The issue is in Rails, specifically Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path. Sprockets::Helpers::RailsHelper::AssetPaths inherits from ActionView::AssetPaths and overrides a number of methods. When compute_public_path is called through the Sass::Rails::Resolver#public_path method is sass-rails, the rails sprocket helper picks up the task of resolving the asset. Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path defers to super which is ActionView::AssetPaths#compute_public_path. In this method there is a condition of has_request? on rewrite_relative_url_root as seen below:
def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
...
source = rewrite_relative_url_root(source, relative_url_root) if has_request?
...
end
def relative_url_root
config = controller.config if controller.respond_to?(:config)
config ||= config.action_controller if config.action_controller.present?
config ||= config
config.relative_url_root
end
If you look at the internals of rewrite_relative_url_root it relies on a request to be present and the ability to derive it from the controller variable in order to resolve the relative url root. The issue is that when sprockets resolves these assets for sass it does not have a controller present and therefore no request.
The solution above didn't work in development mode for me. Here is the solution that I am using to make it work for now:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
resolver = options[:custom][:resolver]
asset_paths = resolver.context.asset_paths
path = resolver.public_path(asset, kind.pluralize)
if !asset_paths.send(:has_request?) && ENV['RAILS_RELATIVE_URL_ROOT']
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path
end
path
end
end
end
end

Resources