I have a rails engine with a built-in file uploader allowing users to upload files to the engine.
If in the application production config config.assets.compile = true then I can see the uploaded images from the engine within the application views.
If config.assets.compile = false then the images from the engine are not available, even after I run assets:precompile ...
in the engine.rb I have set the following:
initializer :assets do |config|
Rails.application.config.assets.paths << root.join("uploads", "my_engine")
end
any ideas?
thanks !!!
You need to add that directory to the precompile list. This extra line should get it for you
initializer :assets do |app|
app.config.assets.paths << Rails.root.join("uploads", "my_engine")
app.config.assets.precompile << Rails.root.join("uploads", "my_engine", "*")
end
Related
When I configured my app files I put my plugin folders under assets and in my config/application.rb file I added the following lines:
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Cnd
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.1
config.assets.paths << Rails.root.join("app", "assets", "fonts")
config.assets.paths << Rails.root.join("app", "assets", "images")
config.assets.paths << Rails.root.join("app", "assets", "bootstrap")
config.assets.paths << Rails.root.join("app", "assets", "rs-plugin-5")
config.assets.paths << Rails.root.join("app", "assets", "magnific-popup")
config.assets.paths << Rails.root.join("app", "assets", "owlcarousel2")
config.assets.paths << Rails.root.join("app", "assets", "morphext")
# 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.
end
end
Everything runs fine on my localhost when I deploy to an amazon ec2 I am getting the following error:
I do not understand why it loads the files locally but when I deploy it is not. I am just deploying in development environment for right now. Not sure if this makes a difference but I am working on my production environment locally so I precompiled assets. The reason I deployed in development is because I just need to show the client quickly the progress.
After some work I figured it out. I had to use this line RAILS_ENV=production bundle exec rake assets:clobber to get rid of the precompile and then everything went back to normal. Now when I am ready for production I need to figure out how to precompile all of the assets including the plugins.
I know a simple solution would be just to manually copy over all the files in the Rails Engine's /public folder to the Rails application's /public folder. However, this means that each installation would require manually copying.
Furthermore because the Javascript files that my engine uses have hard-coded image paths, I cannot simply throw all my static files under app/assets or vendor/assets, as then Rails would copy them over to public/assets. I can't change the path where Sprockets outputs the files as I have other gems that expect their assets to be in the default public/assets folder.
I tried doing something like
class Engine < ::Rails::Engine
if Rails.application.config.serve_static_assets
initializer "static assets" do |app|
app.middleware.insert_before(::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public")
end
end
end
but this only works for development.
Personally, I believe that the best solution would be to update your javascript files to follow Rails' conventions by replacing the hard-coded images in the javascript with the asset path helper - http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets and then throwing everything into app/assets.
With that said, I can think of situations where you may not want to do that, and that may be the case here.
From your post, I'm guessing that you're precompiling assets for production (i.e. - running rake assets:precompile). In that case, you can just hook into the assets:precompile rake task and copy the files over. It would look something like this in your engine's lib/tasks/my_engine_tasks.rake:
Rake::Task["assets:precompile"].enhance do
Rake::Task["my_engine:copy_assets"].invoke
end
namespace :my_engine do
task :copy_assets => :"assets:environment" do
assets = ["file1", "file2"]
assets.each do |asset|
source_file = File.join(MyEngine::Engine.root, 'public', asset)
dest_file = File.join(Rails.root, 'public', asset)
FileUtils.copy_file source_file, dest_file, true
end
end
end
The above is a simple copy operation but you can also manually run sprockets over those files as well. Take a look at the code for the assets:precompile task (lib/sprockets/rails/task.rb in the sprockets-rails gem) and the Sprockets Manifest class (lib/sprockets/manifest.rb in the sprockets gem).
Seems Rails doesnt provide an obvious way to serve static assets from an engine. So heres my dynamic solution for this problem.
module MyApp
class Engine < ::Rails::Engine
isolate_namespace MyApp
initializer "my_app.assets.precompile" do |app|
app.config.assets.precompile << "my_app_manifest.js" ### manifest file required
### Precompile all static assets
### Note in this example use a non-standard folder (app/assets/public/)
["app/assets/images/", "app/assets/public/"].each do |folder|
dir = app.root.join(folder)
if Dir.exist?(dir)
Dir.glob(File.join(dir, "**/*")).each do |f|
asset_name = f.to_s
.split(folder).last # Remove fullpath
.sub(/^\/*/, '') ### Remove leading '/'
app.config.assets.precompile << asset_name
end
end
end
end
end
end
I have deployed my app to heroku, but some assets are not loading, e.g.:
GET https://myapp.herokuapp.com/javascripts/s3_direct_upload.js - 404
GET https://myapp.herokuapp.com/stylesheets/s3_direct_upload_progress_bars.css - 404
the problem is in precompile, I have to add every file manually to assets.rb
but I don't really want to do it, because there are many of them
in my assets.rb I tried:
Rails.application.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 "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
}
and:
Rails.application.config.assets.precompile = false
but it's not working
I've added to application.rb
config.serve_static_files = true
also, //=require from my precompilled assets are not included into header
everything works good in dev environment on my laptop
what do I need to change to make it work in production?
Update
I use helper, to include some js and css files in views:
def javascript(*files)
content_for(:foot) { javascript_include_tag(*files) }
end
and in my view I have:
<% stylesheet 's3_direct_upload_progress_bars' %>
<% javascript 's3_direct_upload', 'init.script.js' %>
assets from gem s3_direct_upload are not loading
init.script.js is located in assets/javascripts, so it is loading as it should be
another problem, in my application.js I have:
//= require jquery
//= require jquery.slicknav.min.js
$(function ()
{
$('#menu').slicknav();
});
after assets:precompile it looks okay, but in console I have error:
$(...).slicknav is not a function
so it was compiled wrong? everything works good in development environment
Update 2
Ignore the second problem, I found second require for jquery, it caused this error
but I still can't include assets from gem without precompile,
can I somehow disable this behavior? I just want include some assets for specific actions without headache
By default Rails 4 will not serve your assets. To enable this functionality you need to go into config/application.rb and add this line:
config.serve_static_assets = true
Alternatively you can achieve the same result by including the rails_12factor gem in your Gemfile:
gem 'rails_12factor', group: :production
This gem will configure your application to serve static assets so that you do not need to do this manually in a config file.
Hope this will work for you.
I am trying to set up asset pipeline on a older rails app that i have so that i can start using CoffeeScript. i am using ruby 1.9.3-p327 and Rails 3.2.13. I used to stash all my JS, CSS and my images in the public/ folder. This is what i have done so far ->
I moved them all to app/assets, i added the manifest files for both JS and CSS call //= require_tree ..
Added the following gems
group :assets do
gem 'coffee-rails'
gem 'uglifier'
gem 'sass-rails'
gem 'therubyracer'
end
Removed all my javascript_include_tags except for = javascript_include_tag 'https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js'
Added the following to my config/application.rb file
# 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'
Within the config/environments/development.rb file set
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
I added to the config/environments/production.rb
# Compress JavaScripts and CSS
config.assets.compress = true
# Choose the compressors to use
# config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :yui
# 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
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
I re-read the section on the Asset Pipeline just to see if i messed up anything. But so far none of the assets are pulling through from app/assets the only one that is working is the jquery.min.js that i have coming in through include_tag i have tried removing it and trying again no dice.
I have tried bundle exec rake assets:clean, and bundle exec rake assets:precompile, both of which run without issues. and have bundled since adding the gems for the assets, and restarted pow each time.
I am not sure if i am going through this all wrong or i have missed a step? any one gone through this before and tips or clues would be much appreciated.
You said you removed all the javascript_include_tag statements. Assuming you named the manifests app/assets/javascripts/application.js and app/assets/stylesheets/application.css, you'll need to include those in your layout:
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
Otherwise, Rails won't know to load your manifest files
Also, you shouldn't be using rake assets:precompile in development. If you do, then anytime you change a JS/CSS file, you'll have to recompile the assets before your changes show up.
I copied config/environments/development.rb to config/environments/ci.rb.
When I run with RAILS_ENV=development, the asset search path includes my gem vendor directories, in particular for jquery-ui-rails. However, when I run with RAILS_ENV=ci it does not.
From the console, Rails.application.config.assets.paths evaluates to the following with development
irb(main):002:0> Rails.application.config.assets.paths
=> ["/var/www/ci/conflux/app/assets/images",
"/var/www/ci/conflux/app/assets/javascripts",
"/var/www/ci/conflux/app/assets/stylesheets",
"/var/www/ci/conflux/vendor/assets/stylesheets",
"/opt/comcast/ruby1.9.3/lib/ruby/gems/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts",
"/opt/comcast/ruby1.9.3/lib/ruby/gems/1.9.1/gems/jquery-ui-rails-1.0.0/vendor/assets/images",
"/opt/comcast/ruby1.9.3/lib/ruby/gems/1.9.1/gems/jquery-ui-rails-1.0.0/vendor/assets/javascripts",
"/opt/comcast/ruby1.9.3/lib/ruby/gems/1.9.1/gems/jquery-ui-rails-1.0.0/vendor/assets/stylesheets"]
but for ci I only get the following:
irb(main):002:0> Rails.application.config.assets.paths
=> ["/var/www/ci/conflux/app/assets/images",
"/var/www/ci/conflux/app/assets/javascripts",
"/var/www/ci/conflux/app/assets/stylesheets",
"/var/www/ci/conflux/vendor/assets/stylesheets",
"/opt/comcast/ruby1.9.3/lib/ruby/gems/1.9.1/gems/jquery-rails-1.0.19/vendor/assets/javascripts"]
Have you added the ci environment into config/application.rb?
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test ci)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
I think #mccannf has the right answer but if it isn't the problem, have you added the jquery-ui-rails gem to the the ci group into Gemfile?