在 gem 中使用 rails 作为依赖项

Posted

技术标签:

【中文标题】在 gem 中使用 rails 作为依赖项【英文标题】:Using rails inside gem as a dependency 【发布时间】:2013-09-04 05:33:19 【问题描述】:

在浏览active-admin 代码时,我发现Gemfile 包含rails 条目。

rails_version = detect_rails_version
gem 'rails', rails_version

这是否意味着 active-admin 在内部创建了一个不是主要 rails 应用程序的 rails 服务器?

如果,这是否会导致性能问题并且将其用于复杂的 Rails 应用程序是一种不好的做法?

如果,在active-admin Gemfile中有什么用?

用不同的关键字搜索了很多,这只会导致 gem 安装和相关结果。

如果有人提出一些见解,我会很高兴。 谢谢:)

更新1: 在 Gaurish 回答和googling 之后,似乎 gem 中的 Gemfile 用于在内部列出 gem 所需的依赖项。 但它产生了另一个问题,当应用程序 gem 和 gem 的 gem 冲突时会发生什么?

更新2: 我们可以独立使用 active-admin,因为它有 rails 作为依赖项吗? (只需通过gem install active-admin 安装active-admin,而不是将其保存在其他rails 应用程序中。)

【问题讨论】:

【参考方案1】:

没有。这似乎是一个捆绑程序问题。 this code 只是声明了对 rails 的依赖。声音很奇怪?这就是我认为正在发生的事情。

通常的方法是使用以下行在.gemspec 文件中声明您的依赖项:

s.add_dependency("rails", ">= 3.0.0")

以上几行添加了对 rails v3.0 & above(v3.1,v3.2) 的依赖。现在这适用于其他 gem & bundler 将自动解决依赖关系。但是当您尝试支持多个版本的 rails 时,bundler 可能会感到困惑。

理想情况下,bundler 应该能够自动捆绑(安装)我们 gem 的所有依赖项。还有 gem 依赖的依赖。例如,bundle 应该足够聪明,可以判断是否需要 rails v3.1v3.2,它还需要包含 sass-rails 和 'uglifier',因为它们是 rails 3.1 和 3.2 所要求的。但如果需要 rails v3.0,则无需进行任何额外操作。

但我们生活在不太完美的世界里,所以 bundler 不够聪明。因此,我认为这就是 active-admin 不得不针对 bundler 的缺点采取以下技巧的原因。

unless defined?(RAILS_VERSION_FILE)
  RAILS_VERSION_FILE = File.expand_path("../../../.rails-version", __FILE__)
end

unless defined?(DEFAULT_RAILS_VERSION)
  DEFAULT_RAILS_VERSION = "3.1.0"
end

def detect_rails_version
  return DEFAULT_RAILS_VERSION unless File.exists?(RAILS_VERSION_FILE)
  File.read(RAILS_VERSION_FILE).chomp
end

def write_rails_version(version)
  File.open(RAILS_VERSION_FILE, "w+")|f| f << version 
end


rails_version = detect_rails_version
gem 'rails', rails_version

case rails_version
when /^3\.0/
  # Do nothing, bundler should figure it out
when /^3\.(1|2)/
  # These are the gems you have to have for Rails 3.1 to be happy
  gem 'sass-rails'
  gem 'uglifier'
else
  raise "Rails #rails_version is not supported yet"
end

如果您注意到上面的代码,它会检查当前版本的 rails 是 v3.1 还是 v3.2。如果是,则添加新的两个作为依赖项。这就是这段代码所做的一切。


[更新]

问题 1. 当应用程序 gem 和 gem 的 gem 冲突时会发生什么? 如果它们以这样的方式发生冲突,以至于捆绑器无法找到满足您的应用程序和 gem 的依赖关系的兼容版本。 bundler 将失败并出现类似以下的错误:

Bundler could not find compatible versions for gem "json":
  In Gemfile:
    chef (~> 10.26) ruby depends on
      json (<= 1.7.7, >= 1.4.4) ruby

    berkshelf (~> 2.0) ruby depends on
      json (1.8.0)

问题 2。我们可以单独使用 active-admin 吗 没有铁轨?不,当您执行gem install active-admin 时,rubygems 将自动安装 rails,因为它在 gemspec 文件中列为此 gem 的依赖项。

【讨论】:

感谢您的宝贵时间,但您认为,为什么 Gemfile 会包含对其他宝石(如波旁威士忌)的引用,而普通的 Rails 应用程序中并不需要这些引用? 一般来说,gem 的 Gemfile 应该包含 Rubygems 源代码和一个 gemspec 行,但开发人员有时不遵循这个建议。这就是我们在这里看到的。见yehudakatz.com/2010/12/16/… 是的,没错。但是在 gem 开发中,Gemfile 用于编写 gem 内部使用的 gems 依赖项。 yahuda 在 Ruby 库 最后一点下。 正确。那你的问题是什么? 更新问题以合并您的答案。

以上是关于在 gem 中使用 rails 作为依赖项的主要内容,如果未能解决你的问题,请参考以下文章

降级 gem 时,bundler 可以自动降级 gem 的依赖项吗?

Rails 4 - 具有简单形式的依赖字段的 JS

Ruby On Rails 和挑战 API

Quickbooks&Rails 5,无法创建发票

我可以在 gemfile 中强制 gem 的依赖项吗?

在 Ubuntu 上安装 mysql gem 的困难