47

我正在将我们的 Rails 2.3.8 应用程序之一升级到 Rails 3,并且遇到了一个令人讨厌的捆绑器和部署问题。我在 Windows 机器上开发应用程序,但生产环境运行的是 Ubuntu Linux。现在,我的问题是捆绑器忽略了mysql生产环境中的 gem,Passenger 吐出:“!!!缺少 mysql gem。将它添加到您的 Gemfile:gem 'mysql', '2.8.1'”

这是我的Gemfile

# Edit this Gemfile to bundle your application's dependencies.
# This preamble is the current preamble for Rails 3 apps; edit as needed.
source 'http://rubygems.org'

gem 'rails', '3.0.0'
gem 'net-ldap', :require => 'net/ldap'
gem 'highline', :require => 'highline/import'
gem 'mysql', '2.8.1'
gem 'net-ssh', :require => 'net/ssh'

# Bundle gems for the local environment. Make sure to
# put test-only gems in this group so their generators
# and rake tasks are available in development mode:
group :development, :test do
  gem 'fakeweb', :require => 'fakeweb'
  gem 'flexmock', :require => 'flexmock/test_unit'
end

如您所见,mysqlgem 已指定。但是,在部署时,bundler 会忽略它。为什么?原因是 Bundler 生成以下内容Gemfile.lock(仅包括相关部分):

....
mime-types (1.16)
mysql (2.8.1-x86-mingw32)
net-ldap (0.1.1)
....

请注意,它包括特定于平台的 gem。这显然不是我想要的,因为当在 Linux 下运行时,该 gem 不适合(并且似乎被忽略)。

那么,Bundler 是否有任何方法来处理这些问题?或者我是否必须记住Gemfile.lock每次在我的开发机器上运行 bundle install 时手动更改生成的 mysql gem 版本?

先感谢您!

更新

捆绑器团队似乎意识到了这个问题

4

11 回答 11

37

这是Bundler 中的一个已知问题。解决方法是:

  • 在与您的生产环境足够相似的系统上生成 Gemfile.lock,您可以获得与您的生产平台相匹配的结果。实际上,这意味着如果您的生产系统是 Windows,您只能在 Windows 上生成 Gemfile.lock 文件。
  • 根本不要提交 Gemfile.lock 文件,并在部署时确定对生产机器的依赖关系(bundle install没有--deploy)。虽然一般不推荐,但在修复错误之前,这是一种常用的解决方法。例如,这是 Heroku 提供的推荐解决方案。
  • 切换到 JRuby,它将在 Windows 和 Linux ( java) 中具有相同的平台字符串。我不认真推荐这个,但我相信它会解决问题。
  • 修复Bundler源码中的问题,即帮助Bundler团队修复bug。:)
于 2010-11-06T16:29:13.923 回答
8

我有一个类似的问题。我希望能够在我的 Gemfile 中写这样的东西:

platforms :ruby do                      # linux
  gem 'nokogiri', "1.5.0.beta.2" 
end

platforms :mswin do
  gem 'nokogiri', "1.4.4.1" 
end

但是,bundler 告诉我不允许。因此,在这种特定情况下有效的解决方法是指出一系列版本:

gem 'nokogiri', ">= 1.4.4.1", "<=1.5.0.beta.2" 

哪个 - 目前 - 在我的 Windows 计算机上提供 1.4.4.1 版本,在我的 linux 计算机上提供 1.5.0.beta.2 版本。也许您可以编写一个类似的丑陋解决方法;-)

于 2010-12-07T14:50:00.727 回答
5

我们在 Engine Yard 的工程师已经向 Bundler 提交了一个补丁来解决这个问题,如果在不同的平台上解冻 gem。在运行 RailsInstaller 演示教程后,我们在尝试部署许多 Windows 时遇到了同样的问题。我们发现的最佳解决方法是执行以下操作:

  1. bundle install在你的开发机器上像往常一样
  2. 浏览Gemfile.lock并且如果有任何带有 的行,请-x86-mingw32删除该部分。
    • bcrypt-ruby (3.0.1-x86-mingw32)变成bcrypt-ruby (3.0.1)
  3. ruby在“平台”部分下添加Gemfile.lock
  4. Gemfile确保在平台标志中明确指定所需的 gem 。(不知道这是否需要,但它没有伤害)
    • Gemfile:`gem 'bcrypt-ruby', '~> 3.0', :platform => 'ruby'
  5. bundle install再次将保留该bcrypt-ruby (3.0.1)行并bcrypt-ruby (3.0.1-x86-mingw32)再次添加。

如果您对 Bundler 补丁感到好奇,可以在https://github.com/carlhuda/bundler/pull/1451获得通知

希望这可以帮助任何仍在寻找答案的人。

于 2011-10-04T15:28:06.210 回答
2

我以前遇到过这个问题,使用mysql2 gem 确实解决了这个问题。我知道这不是您要寻找的答案,但是将其与Diego的答案结合起来,您就可以了。

于 2010-11-04T07:46:08.327 回答
2

您是否尝试过使用rvm此处的链接)?它可以安装隔离的 Ruby 虚拟机和 Gemset,因此您可以使用更类似于生产环境的环境。老实说,我不知道它是否能解决您的问题,但值得一试。

无论如何,我知道这不是您想听到的答案,但是恕我直言,Windows 并不是在 Rails 中开发时最好的平台。我最近买了一台 MacBook,主要是为了开发 Rails 应用程序,它可以让你免去很多麻烦。你也可以在你的开发机器上安装 Linux 并使用它,这比使用 Windows 端口或 Cygwin 更好。

于 2010-11-08T07:49:07.123 回答
2

我认为问题在于 mysql gem 没有正确发现所需的标头。您可以通过使用mysql2 gem来解决此问题,您只需更新数据库适配器以database.yml进行 ActiveRecord 集成。

此外,如果绝对必要,您可以将构建标志传递给 C 扩展 gem:

bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config.

于 2010-11-03T19:56:28.537 回答
1

不要将Gemfile.lock您的宝石投入生产。您必须bundler install在生产中再次运行。

于 2010-09-05T10:31:12.987 回答
1

你可以这样做:

platforms :ruby do
  gem "sqlite3-ruby", :require => "sqlite3", :group => [:development, :test]
end

platforms :jruby do
  gem 'activerecord-jdbc-adapter', :require => false
  gem "jdbc-sqlite3", :require => false
end

顺便说一句,您应该将 Gemfile.lock 放入版本控制中,因为这样所有机器都将使用相同的 gems 版本运行应用程序。

于 2010-09-20T01:40:35.463 回答
0

我遇到了这个问题,然后最终为这个痛苦的任务编写了脚本。 http://gouravtiwari.blogspot.com/2011/03/development-on-windows-deploying-to.html

于 2011-03-24T20:48:28.560 回答
0

我为此找到的最佳解决方案是,在本地开发环境和生产环境中使用不同的平台时,始终ruby使用Gemfile.lock.

您可以通过设置 Bundler 配置值来完成此操作

bundle config set --global force_ruby_platform 'true'

这样,捆绑包将始终默认安装 ruby​​ 平台 gem。但这意味着所有需要在特定平台上进行本机扩展的 gem 都必须进行编译,因此您需要确保在本地和生产机器上都安装了所需的工具和库。

于 2021-03-20T14:52:32.647 回答
0

我为我们的开发人员暂存版本部署到 Linux,为生产和我们的用户暂存版本部署到 Windows。因此我需要一个 .lock 文件(生产和登台仅使用 .lock 文件,并且我想确保我使用的是保存在 .lock 文件中的开发人员使用的 gem 版本)。

所以我将三个版本的 Gemfile.lock 提交到我的存储库。有正常的 Gemfile.lock。我还为每个不同的平台(_win 和 _linux)创建了锁定文件,它们是在该平台上创建的 Gemfile.lock 的副本。

将两个 .lock 文件都放入 repo 需要额外的一轮提交。因此,如果我必须在 Windows 拉取请求后在我的 Mac 上进行捆绑安装,我将预先存在的 .lock 文件复制为 windows 版本,并将我的新 .lock 文件复制为 linux 版本。然后我发出拉取请求来更新锁定文件。

部署时,我用正确的版本覆盖 Gemfile.lock。

于 2020-12-29T17:57:27.560 回答