I'm writing a rails engine that has some dependencies. I've specified the dependencies in the gemspec and the engine is finding them when I run bundle install
(i.e. Gemfile.lock looks correct). When I want to use the plugin in a Ruby file, I can do so but need to explicitly require dependency-name
at the top of the file.
However, when I want to use the dependency's asset pipeline, sprockets can't find it.
The app I'm using (for now) is the dummy app that comes in a rails plugin's test folder. Sprockets can find the assets if I specify them in the engine's Gemfile (which is really the dummy app's Gemfile), but not if I specify them in the gemspec. I don't want to rely on the Gemfile because that means that any app that uses my plugin will need to manually add all my dependencies to their Gemfile. For the same reason I don't want a solution that involves updating the app's config file.
This works (in a ruby file) when dependency is included from gemspec:
require 'dependency-name'
but this (in a JS file) doesn't work when dependency is included from gemspec:
//= require 'dependency-name'
Neither require
is needed when dependency is included from Gemfile. I think it's pretty clear but let me know if you need more specifics.
I needed to include the dependency explicitly in my engine.rb in order for its assets to end up in my asset pipeline. Not sure why this is necessary, as Alastor's answer sounded correct to me. It's worth noting that the dependencies are gems that I created using bundler, though I don't see why that should make a difference.
module MyRailsPluginFull
class Engine < ::Rails::Engine
require 'dependency1'
require 'dependency2'
end
end
Added 11/23/12
Having spent some more time working with Engines, I think I understand this more fully now. Gemspecs are just of a list of dependencies that are required, but the gemspec doesn't instruct the application, on startup, to load the files from those dependencies. Gemfiles, on the other hand, do load all the files during startup.
Added 3/20/2015
My statement from over 2 years ago that "Gemfiles, on the other hand, do load all the files during startup" is not entirely true. It's mostly true in Rails, which by default runs Bundler.require
to require all dependencies listed in the Gemfile, as shown in the generator file here -- note that while the default behavior of Rails changed from Rails3 to Rails 4 as discussed here, both use Bundler.require
. However, there is a strong case to be made for using Bundler.setup
and then an explicit require "dependency1"
in whichever file actually depends on depedency1
.
See this discussion of Bundler.require
versus Bundler.setup
.
Also, as @nruth points out in the comments, this may lead to loading of unnecessary classes. However, if the dependency is well designed, its classes will mostly be autoloaded, creating minimal overhead for requiring the entire dependency. Alternatively, if it defines its engine in a file that can be required in in isolation, you can just include the engine file, which should add the necessary files to your asset path, allowing you to require its assets in your CSS & JS manifests. See this bootstrap-sass example, where the gem both adds all its assets to config.assets.paths
and adds some of them to config.assets.precompile
.
While this question is a few years old and I don't even remember what Rails Engine I was writing at the time, I suspect the right way to do it would have been closer to this:
module MyRailsPluginFull
class Engine < ::Rails::Engine
initializer 'bootstrap-sass.assets.precompile' do |app|
require 'dependency1'
# add dependency1's assets to the list of paths
app.config.assets.paths << ...
end
end
end
But note that this should not be necessary--the dependency itself should have defined this initializer so that simply requiring it would be sufficient, as the bootstrap example above does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With