gemspec中包含的依赖项未添加到rails引擎中的资产管道中 [英] Dependency included in gemspec not added to asset pipeline in rails engine

查看:108
本文介绍了gemspec中包含的依赖项未添加到rails引擎中的资产管道中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个具有一些依赖关系的rails引擎。我在gemspec中指定了依赖关系,当我运行 bundle install 时(即Gemfile.lock看起来正确),引擎找到它们。当我想在Ruby文件中使用插件时,我可以这样做,但需要在文件顶部显式地 require dependency-name



然而,当我想使用依赖项的资产管道时,链轮无法找到它。



我正在使用的应用程序现在)是一个虚拟应用程序,它来自一个rails插件的测试文件夹。如果我在引擎的Gemfile(这实际上是虚拟应用程序的Gemfile)中指定它们,链轮可以找到资产,但如果我在gemspec中指定它们,则不会找到它们。我不想依赖Gemfile,因为这意味着任何使用我的插件的应用程序都需要手动将所有依赖关系添加到他们的Gemfile中。出于同样的原因,我不想要一个涉及更新应用程序配置文件的解决方案。



当从gemspec包含依赖关系时,它可以工作(在ruby文件中):

  require'dependency-name'

但是这个(在一个JS文件中)在从gemspec包含依赖的时候不起作用:

  // = require'dependency-name'

require 。我认为这很明显,但让我知道你是否需要更多细节。

解决方案

我需要明确地在我的引擎中包含依赖项.rb以便其资产最终进入我的资产管道。不知道为什么这是必要的,因为阿拉斯托尔的回答听起来对我来说是正确的。值得注意的是,依赖关系是我使用bundler创建的gem,尽管我不明白为什么这会有所作为。

  module MyRailsPluginFull 
class Engine< :: Rails :: Engine
require'dependency1'
require'dependency2'
end
end

新增11/23/12

我花了更多时间与Engines合作,我现在更全面地理解这一点。 Gemspec只是需要的依赖项列表,但gemspec不会指示应用程序在启动时从这些依赖项加载文件。另一方面,Gemfiles会在启动过程中加载所有文件。



新增3/20/2015



<2>我2年多前发表的声明称,Gemfiles在另一方面在启动时加载所有文件并不完全正确。在Rails中大部分情况都是如此,默认情况下运行 Bundler.require 来要求Gemfile中列出的所有依赖项,如生成器文件这里 - 请注意,虽然默认行为的Rails从Rails3更改为Rails 4,如这里所述,都使用 Bundler.require 。然而,使用 Bundler.setup 然后显式需要dependency1是一个很好的例子。无论哪个文件实际取决于 depedency1
请参阅 Bundler的此讨论。需要 Bundler.setup



另外,正如@nruth指出的评论,这可能会导致加载不必要的类。但是,如果依赖性设计得很好,它的类将主要自动加载,从而为需要整个依赖关系创造最小的开销。或者,如果它将引擎定义在可单独需要的文件中,则可以包含引擎文件,该引擎文件应将必要的文件添加到资产路径中,从而允许您在CSS& JS清单。请参阅此bootstrap-sass示例,其中gem都将其所有资产添加到 config.assets.paths ,并将其中一些添加到 config.assets.precompile



虽然这个问题已经过去几年了,我甚至不记得当时我在写什么Rails引擎,但我怀疑正确的做法是更接近于此:

  module MyRailsPluginFull 
class Engine< :: Rails :: Engine
initializer'bootstrap-sass.assets.precompile'do | app |
require'dependency1'

#将dependency1的资产添加到路径列表中
app.config.assets.paths<< ...
end
end
end

但请注意这不应该是必要的 - 依赖本身应该已经定义了这个初始化器,所以只需要它就足够了,就像上面的引导示例一样。


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.

这篇关于gemspec中包含的依赖项未添加到rails引擎中的资产管道中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆