How to precompile assets without subfolder specific? - ruby-on-rails

How precompile assets without subfolder specific?
Example, my assets is that way:
app/assets
/fonts
/images
sprite.png
/sprite
icon1.png
icon2.png
...
iconX.png
/stylesheets
/javascripts
How I configure assets to precompile without folder /sprite in imagem ?

A year ago this worked for me. I no longer do it, but I don't know why it wouldn't continue to work. Put this into config/application.rb (or config/initializers/assets.rb):
config.assets.precompile = [
lambda do |filename, path|
path =~ /app\/assets/ &&
!%w(.js .css).include?(File.extname(filename)) &&
path !~ %r{app/assets/images/sprite/}
end,
/(?:\/|\\|\A)application\.(css|js)$/
]
You may want to update the above to better match what's in the source below. Looks like it's changed a little bit, but this should get you where you need to go.
See https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb#L61

Related

Image Asset Not Loading In Production

I'm running Rails 5.2.2. I recently separated some admin code from my frontend and in the process moved my controllers, views, css & JS to folders in either frontend or admin respectively.
In development, everything works fine. In production, I am unable to load image assets from my css.scss files using the following line background: url(arrow.png) no-repeat left center; (located in app/assets/stylesheets/frontend/application.css.scss).
My assets has the following file structure:
assets/
config/
images/
admin/
frontend/
products/
another_folder/
javascripts/
admin/
frontend/
stylesheets/
admin/
frontend/
I did not have to change any of my image tags in my views once I made these changes for my images in assets/images/products so I figured that I wouldn't have to do that anywhere else either; things just seemed to work. However, in production the arrow.png returns a 404. When I inspect the image request, the link to the image is /assets/frontend/arrow.png. I use the RAILS_ENV=production flag when compiling assets. I have also run rake assets:clobber with the production flag then tried compiling the assets again. I've deleted all browsing data.
Here are my server logs where the image is requested:
I, [2019-08-01T05:06:22.496953 #6733] INFO -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] Started GET "/assets/frontend/arrow.png" for 35.188.197.210 at 2019-08-01 05:06:22 +0000
F, [2019-08-01T05:06:22.501395 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643]
F, [2019-08-01T05:06:22.503739 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] ActionController::RoutingError (No route matches [GET] "/assets/frontend/arrow.png"):
UPDATE:
Adding this to a view works fine in production so I can confirm the asset does indeed compile properly.
<%= image_tag("frontend/arrow.png") %>
For Rails 5, please try to change following configuration:
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
to
config.public_file_server.enabled = true
OR
you can set RAILS_SERVE_STATIC_FILES true in your passenger_env_var. That will also work.
Helo is this code works for you?
background: image-url(arrow.png) no-repeat left center;

How to precompile a pdf asset in Rails?

In Rails 3.2.11 app I'm trying to publish my app to Heroku.
In the assets folder I have a pdf subfolder with some pdf files inside.
In my production.rb file I have added the following:
config.assets.precompile += %w[*.png *.jpg *.jpeg *.gif *.pdf]
config.assets.precompile += ["*.js"]
config.assets.precompile += ["*.css"]
config.assets.precompile += ['pdf/*']
config.assets.precompile += %w( ricerca_wg.pdf )
If I check the pdf assets paths on my console I get:
Rails.application.config.assets.paths
# [
# "/Users/Augusto/Sites/wisegrowth/app/assets/images",
# "/Users/Augusto/Sites/wisegrowth/app/assets/javascripts",
# "/Users/Augusto/Sites/wisegrowth/app/assets/pdf",
# "/Users/Augusto/Sites/wisegrowth/app/assets/stylesheets",
# "/Users/Augusto/Sites/wisegrowth/vendor/assets/javascripts",
# "/Users/Augusto/Sites/wisegrowth/vendor/assets/stylesheets",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/jquery-rails-2.3.0/vendor/assets/javascripts",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/coffee-rails-3.2.2/lib/assets/javascripts",
# "/Users/Augusto/.rvm/gems/ruby-1.9.3-p551/gems/formtastic-2.1.1/app/assets/stylesheets"
# ]
But when I run
rake assets:precompile RAILS_ENV=production
everything is precompiled BUT the pdf files and in my production app on Heroku I get the following error:
ActionView::Template::Error (ricerca_wg.pdf isn't precompiled):
I don't think a pdf must be "precompiled".
if you just want to access the pdf from your app without using another service like S3, you can just put that pdf folder on your public folder of the rails app, and they will be available on the app as an static file.
www.domain.com/pdf/ricerca_wg.pdf
just be sure that the public/pdf folder isn't in the gitignore and it must work.
I believe the ricerca_wg.pdf is under /Users/Augusto/Sites/wisegrowth/app/assets/pdf/? If not, simply
remove config.assets.precompile += %w( ricerca_wg.pdf )
move ricerca_wg.pdf under /Users/Augusto/Sites/wisegrowth/app/assets/pdf/ - it should be precompiled along with other pdf files from this directory

Can you configure Rails to precompile ALL files under a directory

Yes, there are a million questions asking how to register a directory for the assets pipeline. But my question is slightly different...
I'm building a basic theme system and the file structure will look like this:
app/assets/skins/
some_theme/
style.css.scss
fonts/
font1.woff
font2.woff
images/
whocares.png
another_theme/
...
As you can see, the theme-specific assets are bundled in their own directories. When I new theme gets added, I don't want it to require any tinkering with the configurations.
Can I configure the asset pipeline to search/precompile ALL the files under app/assets/skins/?
I think I want something like this in application.rb...
config.assets.paths << Rails.root.join('app', 'assets', 'skins', '**')
...but this isn't how it works. How does it work?
To include all your scripts: add to your app/assets/javascripts/application.js:
//= require_tree ../skins
To include all your styles: add to your app/assets/stylesheets/application.css:
*= require_tree ../skins
Or the equivalent syntax for sass (better than using comments):
#import '../skins/**/*'
To include all other assets add to config/initializers/assets.rb:
Dir.glob( Rails.root.join( 'app', 'assets', 'skins', '**' ) ).each do |path|
Rails.application.config.assets.paths << path
end
And to access for example app/assets/skins/a_theme/skin.png you can use view helpers like:
<%= image_tag 'skin.png' %>
And in your sass files helpers like:
background-image: image-url('skin.png')
The same for fonts assets.
UPDATE: just to clear a point: with Dir.glob if 2 images have the same name in different paths only the first in paths list will be used

Rails asset pipeline flattens directories

I've been using asset_sync, to move our static assets to Amazon S3, and I've noticed that when I precompile my assets (using foreman run rake assets:precompile), the base directories get flattened. They go from:
/app
/assets/
/images
image.png
image2.png
/subdir
image3.png
/javascripts
script.js
/stylesheets
style.css
To:
/public
/assets/
image.png
image2.png
/subdir
image3.png
script.js
style.css
It keeps any subdirectories, but the base directories get removed for some reason.
Is it possible to disable this? I'd like to keep my S3 assets organized into directories. I could probably resolve this by adding additional directories so that the structure is the following.
/app
/assets/
/images
/images
image.png
image2.png
/subdir
image3.png
/javascripts
/javascripts
script.js
/stylesheets
/stylesheets
style.css
But that just seems like a dirty solution.
I'm configuring my assets for precompiling with:
Rails.application.config.assets.precompile = []
Rails.application.config.assets.precompile += ['application.js']
Rails.application.config.assets.precompile += Loader.js_files
Rails.application.config.assets.precompile += ['*.css', '*.png', '*.svg', '*.jpg']
My environment has the following variables":
ASSET_SYNC_GZIP_COMPRESSION=true
ASSET_SYNC_MANIFEST=true
ASSET_SYNC_EXISTING_REMOTE_FILES=keep
AWS_ACCESS_KEY_ID=xxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxx
FOG_DIRECTORY=aws-example
FOG_PREFIX=/assets/
FOG_PROVIDER=AWS
FOG_REGION=us-west-1
Have you configured asset_sync correctly for the application you are creating?
AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.fog_directory = ENV['FOG_DIRECTORY']
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
config.prefix = 'assets'
config.public_path = Pathname('./public')
end
Depending on the type of application you need to configure the prefix and the public_path. Check out the Sinatra/Rack support section https://github.com/AssetSync/asset_sync for more information. Hope puts you on the right path.

How do I use config.assets.precompile for directories rather than single files?

How do I use config.assets.precompile in production to only include the files in 'lib/assets/javascripts', 'lib/assets/stylesheets', 'vendor/assets/javascripts' and 'vendor/assets/stylesheets'?
Basically something like:
config.assets.precompile += %w( pagespecific.js anotherpage.js )
But used to auto include files in specific directories that are not 'app/assets/javascripts' or 'app/assets/stylesheets'.
*edit: adding the solution I ended up using for page specific js
config.assets.precompile += ['pages/*.js']
You can simply write it like this:
config.assets.precompile += ['directory/*']
The point of compiling assets is to build one (or a small number of) files to minimize the number of HTTP requests from the browser.
If you're going to serve each file individually, then why not just disable precompile?
To use precompile as intended, build an entire directory into one file using Sprockets' require_directory:
//= require_directory ./awesome_js_app
...and list that file in your config.assets.precompile array.
By default, all CSS is built into application.css & JS into application.js. You can add more top-level files to compile with the precompile directive in config/environments/production.rb (and other envs if you wish.) For example:
config.assets.precompile += %w( public.css public.js )
Then the Sprockets //= require ... directives in those top-level files will determine the composition of final compiled file.
You can use these additional top-level files in your layouts to have different CSS & JS for certain views.
It's probably a bit better to include this as an asset path(as per your example solution it would be):
config.assets.paths << Rails.root.join('app', 'assets', 'javascripts', 'pages')
It also allows you to include paths not in the assets directory (for example with including the bootstrap-sass). These paths are then added to your assets folder in your public directory, and pushed to your asset location if using something like asset_sync.
I found this link, and think may be it helpful for you, please see
keithgaputis's answer. Rails config.assets.precompile setting to process all CSS and JS files in app/assets
I think you can do like following.
# In production.rb
config.assets.precompile << Proc.new { |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 "excluding asset: " + full_path
false
else
puts "including asset: " + full_path
true
end
else
false
end
}
As of Sprockets 3 you can use a manifest.js file to declare which files or directories are precompiled. See upgrade docs. So in your config you would add:
config.assets.precompile = %w(manifest.js)
Then in app/assets/config/manifest.js you can have
//= link_directory ../pages .js
Use link_tree if you want js files in nested sub-directories to be precompiled too.

Resources