5

I need to have different versions of a gem for development and production, so I put the following in my 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

but if i try to do bundle install or even just rails console I get the above error

I have tried

bundle install --without production

but I still get the error message. FYI: I need to do this because I am going thru the rails tutorial and there is a conflict that arises between windows, ruby 2.0.0 and bcrypt and Heroku so I am using bcrypt 3.1.2 on windows (with a modification to the active record gemfile) and bcrypt 3.0.1 on Heroku.

See this for more details: Issues using bcrypt 3.0.1 with ruby2.0 on Windows

I basically did what is mentioned in the first answer

EDIT

###################################################################

As the answer below points out, I really should be using the same version in both production and development (even tho I am just working thur a tutorial). What I ended up doing is monkey patching ActiveModel to use

gem 'bcrypt-ruby', '3.1.2'

rather than

gem 'bcrypt-ruby', '~> 3.0.0'

in secure_password.

I accomplished this by placing the following in 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

and then adding the following to config/environment.rb

require File.expand_path('../../lib/secure_password_using_3_1_2.rb', __FILE__)
Community
  • 1
  • 1
nPn
  • 16,254
  • 9
  • 35
  • 58
  • You said you get "the above error", but you don't provide the error. – Peter Alfvin Jan 04 '14 at 00:18
  • Sorry ... it was in my title, but it was too long. Basically it complains that I have two versions in the gem file. I am not at the computer right now, so I cant give the exact message just now – nPn Jan 04 '14 at 00:43

3 Answers3

7

How about this?

gem "my_gem", ENV["RAILS_ENV"] == "production" ? "2.0" : "1.0"

RAILS_ENV=production bundle
Victor Moroz
  • 9,167
  • 1
  • 19
  • 23
  • I think this works. I would mark it as the answer, but I _think_ the "right" solution is the monkey patch I did in my edited version of the question – nPn Jan 04 '14 at 02:15
1

The short answer is that you can't do that easily. Bundler is intended to enforce that all gems are using the same version between development and production. Using different versions can lead to subtle bugs.

Why don't you want to run 3.1.2 in production?

Tim Moore
  • 8,958
  • 2
  • 23
  • 34
  • I am using rails 3.2.16 on heroku and it is asking for bcrypt ~》 3.0.0 in has_secure_password.rb. I hacked that file on my windows install. I assumed I could not do that for the production or can I some how provide an alternative has_secure_password.rb ? – nPn Jan 04 '14 at 00:55
1

I know I'm late to the party, but i couldn't find an answer anywhere.

I was trying to find an answer to this question as i wanted to deploy to a prerelease gem to my staging environment and a full gem version to my production. I didn't want my production environment to use anything like "1.0.2.pre1" or anything like that until it was released, thereby having the version "1.0.2". The reason is a long story :)

version = "3.0.1"

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

gem 'bcrypt-ruby', version

It just runs the block if you have the dev/test group, which assigns the variable.

  • 1
    This won't work when it hits production because when you run `bundle install` and commit the new `Gemfile.lock`, the `3.1.2` version will be written into there and subsequently used in production. – Darth Egregious Oct 13 '16 at 19:22