如何为开发和生产环境指定不同版本的gem?

5
我需要在开发和生产环境中使用不同版本的gem,因此我将以下内容放入我的gemfile文件。
group :development, :test do
  gem 'rspec-rails', '2.11.0'
  gem 'bcrypt-ruby', '3.1.2'
end

group :production do
  gem 'rails_12factor'
  gem 'bcrypt-ruby', '3.0.1'  
end

但是如果我尝试执行bundle install, 或者仅仅是rails console,我会得到上述错误。
我已经尝试过:
bundle install --without production

但我仍然收到错误信息。 FYI: 我需要这样做是因为我正在进行rails教程,而在windows、ruby 2.0.0和bcrypt与Heroku之间存在冲突。 因此,我在windows上使用bcrypt 3.1.2(对active record gemfile进行了修改),而在Heroku上使用bcrypt 3.0.1。 更多详情请参见:Issues using bcrypt 3.0.1 with ruby2.0 on Windows 基本上,我做了第一个答案中提到的内容。
编辑:
###################################################################

正如下面的答案所指出的那样,我在生产和开发中确实应该使用相同的版本(即使我只是在跟着教程学习)。 最终我做了个补丁,使用 ActiveModel 来进行修改。

gem 'bcrypt-ruby', '3.1.2'

相比之下
gem 'bcrypt-ruby', '~> 3.0.0'

在secure_password中实现此功能。

我通过将以下内容放置在lib/secure_password_using_3_1_2.rb中来实现。

module ActiveModel
  module SecurePassword
    extend ActiveSupport::Concern

    module ClassMethods

      def has_secure_password
        # Load bcrypt-ruby only when has_secure_password is used.
        # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library.
        #gem 'bcrypt-ruby', '~> 3.0.0'
        gem 'bcrypt-ruby', '3.1.2'
        require 'bcrypt'

        attr_reader :password

        validates_confirmation_of :password
        validates_presence_of     :password_digest

        include InstanceMethodsOnActivation

        if respond_to?(:attributes_protected_by_default)
          def self.attributes_protected_by_default
            super + ['password_digest']
          end
        end
      end
    end
  end
end

然后将以下内容添加到config/environment.rb中

require File.expand_path('../../lib/secure_password_using_3_1_2.rb', __FILE__)

你说你收到了“上述错误”,但是你没有提供错误信息。 - Peter Alfvin
抱歉...这个问题在我的标题中,但是太长了。基本上它抱怨我在gem文件中有两个版本。我现在不在电脑旁边,所以无法立即给出确切的消息。 - nPn
3个回答

7
这个怎么样?
gem "my_gem", ENV["RAILS_ENV"] == "production" ? "2.0" : "1.0"

RAILS_ENV=production bundle

我认为这个可以工作。虽然我“认为”“正确”的解决方案是我在修改后的问题中所做的猴子补丁,因此我不会将其标记为答案。 - nPn

1
我知道我来晚了,但我无法在任何地方找到答案。
我试图找到这个问题的答案,因为我想将预发布的gem部署到我的staging环境,并将完整的gem版本部署到我的production环境。我不想让我的production环境使用像“1.0.2.pre1”这样的东西,直到它被发布为止,从而拥有版本“1.0.2”。原因是一个漫长的故事 :)
version = "3.0.1"

group :development, :test do
    version = "~> 3.1.2"
end

gem 'bcrypt-ruby', version

如果您有开发/测试组,它只会运行该块,从而分配变量。

1
当你运行bundle install并提交新的Gemfile.lock时,3.1.2版本将被写入其中并在生产环境中使用,因此这种方法在生产环境中不起作用。 - Darth Egregious

1
简短的回答是你不能轻易地这样做。Bundler旨在强制所有gem在开发和生产环境中使用相同的版本。使用不同的版本可能会导致微妙的错误。
为什么你不想在生产环境中运行3.1.2?

我正在Heroku上使用Rails 3.2.16,并且在has_secure_password.rb中,它要求使用bcrypt ~》 3.0.0。我已经在我的Windows安装中对该文件进行了修改。我假设我不能在生产环境中这样做,那么是否可以提供替代的has_secure_password.rb文件呢? - nPn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接