Skip to content

Commit

Permalink
Explain how to upgrade bin/ for Rails 4
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy committed Apr 9, 2013
1 parent 74be6bb commit 9039c50
Showing 1 changed file with 29 additions and 8 deletions.
37 changes: 29 additions & 8 deletions railties/lib/rails/app_rails_loader.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,22 +12,43 @@ def self.exec_app_rails
exe ||= find_executable_in_parent_path exe ||= find_executable_in_parent_path
return unless exe return unless exe


if File.read(exe) =~ /(APP|ENGINE)_PATH/ contents = File.read(exe)
# This is a Rails-generated binstub, let's use it
# This is the Rails executable, let's use it
if contents =~ /(APP|ENGINE)_PATH/
exec RUBY, exe, *ARGV if find_executable exec RUBY, exe, *ARGV if find_executable
Dir.chdir("..") do Dir.chdir("..") do
# Recurse in a chdir block: if the search fails we want to be sure # Recurse in a chdir block: if the search fails we want to be sure
# the application is generated in the original working directory. # the application is generated in the original working directory.
exec_app_rails unless cwd == Dir.pwd exec_app_rails unless cwd == Dir.pwd
end end
elsif exe.match(%r(bin/rails$))
# this is a Bundler binstub, so we load the app ourselves # This is a Bundler binstub. Stop and explain how to upgrade.
elsif exe =~ /bin\/rails$/ && contents =~ /This file was generated by Bundler/
$stderr.puts <<-end_bin_upgrade_warning

This comment has been minimized.

Copy link
@steveklabnik

steveklabnik Apr 9, 2013

Member

is strip_heredoc appropriate here?

Looks like your app's ./bin/rails is a stub that was generated by Bundler.
In Rails 4, your app's bin/ directory contains executables that are versioned
like any other source code, rather than stubs that are generated on demand.
Here's how to upgrade:
bundle config --delete bin # Turn off Bundler's stub generator
rake rails:update:bin # Use the new Rails 4 executables
git add bin # Add bin/ to source control
You may need to remove bin/ from your .gitignore as well.
When you install a gem whose executable you want to use in your app,
generate it and add it to source control:
bundle binstubs some-gem-name
git add bin/new-executable
end_bin_upgrade_warning

Object.const_set(:APP_PATH, File.expand_path('config/application', Dir.pwd)) Object.const_set(:APP_PATH, File.expand_path('config/application', Dir.pwd))
require File.expand_path('../boot', APP_PATH) require File.expand_path('../boot', APP_PATH)
puts "Rails 4 no longer supports Bundler's --binstubs option. You " \
"will need to disable it and update your bin/rails file.\n" \
"Please run: `bundle config --delete bin && rm -rf bin`, then " \
"`rake rails:update:bin` and add the resulting bin/ to git."
require 'rails/commands' require 'rails/commands'
end end
rescue SystemCallError rescue SystemCallError
Expand Down

4 comments on commit 9039c50

@fxn
Copy link
Member

@fxn fxn commented on 9039c50 Apr 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@mislav
Copy link
Member

@mislav mislav commented on 9039c50 Apr 11, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can somebody point me to a technical reason why bin/rails doesn't work if generated by Bundler?

@agis
Copy link
Contributor

@agis agis commented on 9039c50 Apr 11, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mislav I think 22e5ab3 is relevant

@jeremy
Copy link
Member Author

@jeremy jeremy commented on 9039c50 Apr 11, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mislav it's due to the way rails behavior changes depending on whether you're inside a Rails app or outside it.

If you're inside an app, we exec bin/rails and let it handle the in-app rails commands. If you're outside an app, we provide the rails new command to generate apps.

When Bundler overwrites bin/rails with a gem stub, execing the stub will exec the rails executable in the Rails gem. But the rails executable is what just execed bin/rails! Boom.

The major change here is that Rails 4 is treating bin/ as part of your app's source code. This philosophy is at odds with Bundler, which treats bin/ as an ephemeral directory whose contents can be overwritten. Future Bundler (probably 2.0 due to semver constraints) will prompt rather than overwrite and, hopefully, won't treat --binstubs as a sticky option.

Please sign in to comment.