我曾经认为您需要为Rails使用自动生成的binstub才能加载正确的版本,否则您可能会意外加载错误的版本。
但是,我发现无论如何都会加载正确版本的Rails。
考虑以下情况:
# System context
$ ruby --version
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-darwin17]
$ which ruby
/Users/sean/.rbenv/shims/ruby
$ rbenv versions
system
* 2.4.3 (set by /Users/sean/.rbenv/version)
# Install three different versions of Rails
$ gem install rails
$ gem install rails -v 4.2.10
$ gem install rails -v 3.2.22.5
$ gem list | grep rails
rails (5.1.4, 4.2.10, 3.2.22.5)
# Globally, I’m using Rails 5.1.4
$ rails --version
# Creating a new app using Rails 4.2.1
$ rails _4.2.10_ new foo_app
$ cd foo_app
$ which rails
/Users/sean/.rbenv/shims/rails
$ rails --version
Rails 4.2.1
# Creating a new app using Rails 3.2.22.5
$ rails _3.2.22.5_ new bar_app
$ cd bar_app
$ which rails
/Users/sean/.rbenv/shims/rails
$ rails --version
Rails 3.2.22.5
如何加载正确的版本,而不是每次都加载最新版本的Rails?如果工具链足够智能以加载正确版本的Rails,为什么Rails会为自己生成binstub?我对工具链的误解是什么?
(我在这里使用“工具链”这个词,因为我不确定这个魔法在哪里发生:Ruby,Bundler,rbenv或Rails。)
https://github.com/rbenv/rbenv/wiki/Understanding-binstubs
对于上下文,这是从4.2.10开始为Rails自动生成的binstub - 它非常代表Rails 4和5 binstubs看起来像:
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
答案 0 :(得分:0)
你实际上在不知情的情况下使用binstub。
让我们来探究一下这是为什么。
首先,从Rails 4应用中删除Gemfile
和Gemfile.lock
,尝试再次运行rails
,然后您会看到此错误:
$ cd foo_app
$ rails --version
Rails 4.2.1
$ rm Gemfile Gemfile.lock
/Users/sean/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bundler-1.16.0/lib/bundler/shared_helpers.rb:34:in `default_gemfile': Could not locate Gemfile (Bundler::GemfileNotFound)
from /Users/sean/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bundler-1.16.0/lib/bundler/shared_helpers.rb:39:in `default_lockfile'
from /Users/sean/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/bundler-1.16.0/lib/bundler.rb:318:in `default_lockfile'
from /Users/sean/Desktop/apps/foo_app/bin/spring:10:in `<top (required)>'
from bin/rails:3:in `load'
from bin/rails:3:in `<main>'
令人惊讶的是,即使你没有明确地运行bin/rails
,它看起来就像binstubs一样。
现在,重新开始使用干净的Rails 4应用程序,这一次,删除bin
文件夹而不是Gemfiles,你会发现你现在正在运行Rails 5:
$ cd .. && rm -rf foo_app && rails _4.2.10_ new foo_app && cd foo_app
$ rails --version
Rails 4.2.1
$ rm -rf bin
$ rails --version
Rails 5.1.4
我不确定这种魔法在哪里发生:Ruby,RubyGems,Bundler,rbenv或Rails - 但你不需要通过它的binstub显式执行Rails,因为它发生在任何一种方式。