Ruby-on-rails 让 bundler 为不同的平台使用不同的 gem

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3642085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:09:33  来源:igfitidea点击:

Make bundler use different gems for different platforms

ruby-on-railsbundler

提问by Daniel Abrahamsson

I'm working on upgrading one of our Rails 2.3.8 apps to Rails 3, and have run into an annoying problem with bundler and deployment. I develop the application on a Windows machine, but the production environment is running Ubuntu Linux. Now, my problem is that bundler is ignoring the mysqlgem in the production environment, and Passenger spits out: "!!! Missing the mysql gem. Add it to your Gemfile: gem 'mysql', '2.8.1'"

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

Here is my Gemfile:

这是我的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

As you can see, the mysqlgem is specified. However, when deploying, bundler ignores it. Why? The reason is that Bundler generates the following Gemfile.lock(only relevant parts included):

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

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

Notice that it includes the platform specific gem. This is obviously NOT what I want it to do, as that gem is not suitable (and appearently ignored) when running under Linux.

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

So, does Bundler come with any way to deal with these issues? Or do I have to remember to manually change the mysql gem version in the generated Gemfile.lockevery time I run bundle install on my development machine?

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

Thank you in advance!

先感谢您!

Update

更新

It seems like the bundler team is aware of this issue.

似乎 bundler 团队已经意识到这个问题

采纳答案by wuputah

This is a known issue in Bundler. The workarounds are either:

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

  • Generate a Gemfile.lock on a system similar enough to your production environment that you get results that match your production platform. Effectively, that means you can only generate the Gemfile.lock file on Windows if your production system is Windows.
  • Don't commit a Gemfile.lock file at all, and determine dependencies on the production machine at deploy time (bundle installwithout --deploy). While not recommended in general, this is an often-used workaround until the bug is fixed. For example, this is the recommended solution offered by Heroku.
  • Switch to JRuby, which would have the same platform string across both Windows and Linux (java). I don't recommend this seriously, but I believe it would fix the problem.
  • Fix the problem in the Bundler source code, i.e., help the Bundler team fix the bug. :)
  • 在与您的生产环境足够相似的系统上生成 Gemfile.lock 以获得与您的生产平台匹配的结果。实际上,这意味着如果您的生产系统是 Windows,您只能在 Windows 上生成 Gemfile.lock 文件。
  • 根本不要提交 Gemfile.lock 文件,并在部署时确定对生产机器的依赖关系(bundle install没有--deploy)。虽然一般不推荐,但在修复错误之前,这是一种常用的解决方法。例如,这是 Heroku 提供的推荐解决方案。
  • 切换到 JRuby,它将在 Windows 和 Linux ( java) 上具有相同的平台字符串。我不认真推荐这个,但我相信它会解决问题。
  • 修复Bundler源码中的问题,即帮助Bundler团队修复bug。:)

回答by Stefan Pettersson

I have a similiar problem. I would like to be able to write something like this in my Gemfile:

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

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

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

But, bundler tells me I am not allowed. So, my workaround, that works in this specific case is to point out a range of versions:

但是,bundler 告诉我我不被允许。所以,我的解决方法是指出一系列版本:

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

Which - at the moment - give the 1.4.4.1 version on my Windows computer and 1.5.0.beta.2 on my linux computer. Maybe it is possible for you to write a similiar ugly workaround ;-)

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

回答by Evan Machnic

Our engineers at Engine Yard have submitted a patch to Bundler to address this issue and unfreeze the gems if on a different platform. We've been having the same problem with many Windows trying to deploy after running through the RailsInstaller Demo Tutorial. The best fix we've found is to perform the following:

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

  1. bundle installlike normal on your development machine
  2. Go through the Gemfile.lockand if there are any lines with -x86-mingw32, remove that part.
    • bcrypt-ruby (3.0.1-x86-mingw32)becomes bcrypt-ruby (3.0.1)
  3. Add rubyunder the 'Platforms' section in the Gemfile.lock
  4. Make sure to explicitly specify the needed gem in the Gemfilewith the platform flag. (Not sure if this is needed but it doesn't hurt)
    • In Gemfile: `gem 'bcrypt-ruby', '~> 3.0', :platform => 'ruby'
  5. bundle installagain which will keep the bcrypt-ruby (3.0.1)line and add in bcrypt-ruby (3.0.1-x86-mingw32)again.
  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)再次添加。

If you're curious about the Bundler patch, you can get notifications at https://github.com/carlhuda/bundler/pull/1451

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

Hope this helps anyone still looking for answers.

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

回答by Fábio Batista

Have you tried using rvm(link here)? It can install isolated Ruby Virtual Machines and Gemsets, so you can work with an environment more like the one you have in production. I honestly don't know if it will solve your problems, but it's worth a shot.

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

Anyway, I know this is not the answer you want to hear, but IMHO Windows is not the best platform use when developing in Rails. I recently bought a MacBook mainly to develop Rails applications, it saves you from a lot of headaches. You can also install Linux on your development machine and use it, it's way better than using Windows ports or Cygwin.

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

回答by Daniel Mendel

I think the issue is that the mysql gem doesn't properly discover the needed headers. You can fix this by moving over to using the mysql2 gem, you'll just have to update your database adapters in database.ymlfor ActiveRecord integration.

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

Additionally, you canpass build flags to C extending gems if absolutely necessary:

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

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

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

回答by bouchard

I've ran into this issue before, and using the mysql2gem does indeed fix the problem. I know that's not the answer you're looking for, but combine that with Diego's answer and you're golden.

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

回答by Joshua Partogi

Don't commit Gemfile.lockand your gems to production. You have to run bundler installagain in production.

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

回答by Diego Carrion

You can do something like this:

你可以这样做:

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

Btw, you should put your Gemfile.lock into the version control because this way all machines will run the application with the same gems versions.

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

回答by gouravtiwari21

I came across this issue and then ended up writing script for this painful task. http://gouravtiwari.blogspot.com/2011/03/development-on-windows-deploying-to.html

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