Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Revert "Ignore /bin on new apps" -- given the move to default binstub…

…s, we want you to check those in!

This reverts commit 35c554f.
  • Loading branch information...
commit 61b91c4c55bcbd5a2ec85d6e1c67755150653dff 1 parent 227d4e9
@dhh dhh authored
Showing with 3 additions and 4 deletions.
  1. +3 −4 railties/lib/rails/generators/rails/app/templates/gitignore
View
7 railties/lib/rails/generators/rails/app/templates/gitignore
@@ -4,14 +4,13 @@
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
-# Ignore bundler related files
+# Ignore bundler config
/.bundle
-/bin
-# Ignore the default SQLite database
+# Ignore the default SQLite database.
@fxn Owner
fxn added a note

:heart:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
/db/*.sqlite3
/db/*.sqlite3-journal
-# Ignore all logfiles and tempfiles
+# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

73 comments on commit 61b91c4

@josevalim
Owner

There is a reason to not check them in. The binstubs include shebang lines and they are not portable. People with different machines or using different tools (rvm/rbenv) will have different binstubs.

If we are going to allow people to shot their own foot, we should at least warn them.

@dhh
Owner
@fxn
Owner

I am out, but aren't the shebangs /usr/bin/env ruby that will work in most places regardless of the actual interpreter?

@dhh
Owner
@sikachu
Collaborator

I'm agree with @josevalim on this one that the shebang line might cause a problem on multiple environment. I like the fact that we're promoting the usage of binstubs, but since ./bin would be generated anyway from running bundle install — and I'm really sure that you need to run bundle install — there's no reason to unignore that ./bin directory.

@jrgifford

I would argue that using multiple toolchains (rbenv or rvm, or just whatever else you might use) is a good thing, since you can avoid issues where you accidentally hard code something. But that is neither here nor there.

@josevalim - the shebang line on my Ubuntu box (using rbenv) is #!/usr/bin/env ruby. that is about as portable as you can get with a shebang line. Now, if you're in a Windows environment, I could see problems occurring. I'm not entirely sure how Windows/git-bash handles shebangs. that might be worth looking into.

@josevalim
Owner

It's imo an anti-pattern to have developers working on the same app use different tool chains like that.

Isn't it a bit contradictory with this post from 37S blog? My argument being: as the 37S blog post mentioned, companies are more likely to allow people to have different setups (and allow their developers to try different tools like rbenv, chruby, rvm, etc).

I would argue that the organisational failure would be the opposite: to "forbid" people from using their preferred ruby manager since all it does after all is to manage ruby versions and installation.

@listrophy

I'm against this change as well. Why can't binstubs install to .bundle/bin? I know this technically isn't a rails issue, but I find this layout to be preferable.

@hone

I agree with @josevalim here as well. I've been bitten a ton of times b/c of the shebang from different environments. At heroku people use the tools they're most comfortable with, which might mean rvm/rbenv/chruby/linux/mac. I think it's wrong to lock a project into a specific ruby version manager/platform by default with rails.

That debate aside, I'm also looking out for the heroku / rails experience. I used to install every binstubs into bin/, but I ran into some issues where the binstubs might conflict with what users have already put into bin. I have now moved it to vendor/bundler/bin. In PATH I have bin come before the bundler binstubs. The reasoning for this, is that a user's bin should have predence over stuff generated by bundler since they manually put it there in source control. Now, this would probably be ok if everyone used #!/usr/bin/env ruby which is what bundler generates by default, but rbenv uses #!/usr/bin/env ruby-local-exec. This means that these binstubs will override the bundler generated ones. This breaks EVERY new rails app from rbenv users on heroku. :(

I'm not sure how this would look, but we should discuss about trying to move this setting into some shareable config/setting in Bundler 1.3.0 instead of checking in the binstubs. /cc @indirect @wycats.

@dhh
Owner
@dhh
Owner
@mislav

I'm wondering what @dhh meant by "it doesn't work with rbenv", and why is 7173c4f considered necessary. /cc @wycats

A binstub generated with #!/usr/bin/env ruby will work just fine with rbenv, since it will hit the ruby shim and the right ruby version will be picked for the current environment/directory.

As long as executables in ./bin are called from inside the project's directory, rbenv will purr just fine. I see no need for Rails to be aware of rbenv (tools coupling with rbenv goes against rbenv's philosophy).

If you call ./bin executables from outside the directory, yes, then you want ruby-local-exec in your shebang. But since this is advanced usage that makes most sense for deploys, I don't think we need to be terribly concerned about it.

@hone

David, thanks for the response. I mean just that. Some people might have things that conflict.

We don't enforce a specific ruby manager here and explicitly chose not to use one since we provide a single vendored ruby for you to use that's required by the application.

We've been using binstubs since Rails 3.1.x or at least supported that path. People of course always welcome to use bundle exec. The workaround you're suggesting is to go through every file in bin/ and search for any bundler binstub or more constrained rbenev binstub and delete them? We can't blindly delete bin/ since it can contain non ruby/bundler/rails related binaries.

There's another caveat that users who have forked the ruby buildpack and when using it against rails 4, it might break their app and won't know why.

@wilson

If Rails depends on bundler then I think it's reasonable to follow its patterns, and if that means checking in the binstubs then I guess that's what should happen. I just don't think Rails should depend on bundler (or any other platform management tool); of course I think Rails should try to load bundler if it wants and use it if it is there.

I hope this doesn't come across as a derailment; if it does I apologize for my inability to express it clearly enough.
My personal ideal of ruby library design allows for the possibility that it will be loaded from site_ruby, without even rubygems; I would, myself, not depend on bundler (or a non-standard shebang) in anything other than a rubygems/bundler plugin or similar.

@wycats
Collaborator

@wilson Bundler's official position is that people should NOT check in binstubs, as they are not necessarily portable.

Checking in binstubs is a decision that @dhh made because of his strongly held opinion that projects should have a single development environment shared by all developers. Bundler does not take that position.

@just3ws

if you are unable to use the same Ruby manager in production and development, I feel bad for you.

I work on MRI with RVM locally then deploy some apps to Heroku on JRuby, some apps get wrapped in Warfiles and deployed onto Tomcat, other apps run against native Rubies running on Centos, others on Ubuntu.

Will these changes break my Rails apps deployed to heterogenous environments?

@sikachu
Collaborator

From what @wycats have said, I think that support the case that we should not check in binstubs. I still wish that this got reverted until we can find a better solution to tell Bundler to recompile the binstubs when you run bundle install.

@wycats
Collaborator

@just3ws in your situation, and any other situation with heterogeneous environments, I would recommend adding the bin directory to your .gitignore.

@dhh's position above is that such environments are in conflict with Rails conventions, so the .gitignore will default to checking in binstubs.

@krainboltgreene

This really isn't a discussion about portability or development environments, despite those being good discussions. This should be a discussion about how Rails handles creating new applications. Shared environment or not, things that can be generated on the fly (assets, environment config files, binaries) generally shouldn't be checked into the repository. The generation process should (often does) handle platform specific details.

Since we're talking about a default .gitignore a new developer of a rails application should not be allowed to accidentally fill the repository with auto-generated junk. It should be opt-in due to the nature of git, as you're then saying: I want to handle, myself, what changes to this file goes into the repository. Most newbies don't want to handle that.

@just3ws

@wycats thanks. :)

@gilesbowkett

quoting @wycats

Checking in binstubs is a decision that @dhh made because of his strongly held opinion that projects should have a single development environment shared by all developers. Bundler does not take that position.

This seems less like convention over configuration and more like convention over common sense. Maybe that was a bit trolltastic, but choosing what to normalize and what to leave optional is a design decision, and involves tradeoffs. I think this expectation, about how people organize their development environments, goes much too far.

quoting @krainboltgreene

This really isn't a discussion about portability or development environments, despite those being good discussions. This should be a discussion about how Rails handles creating new applications. Shared environment or not, things that can be generated on the fly (assets, environment config files, binaries) generally shouldn't be checked into the repository. The generation process should (often does) handle platform specific details.

I think this is a much wiser operating principle.

@josevalim
Owner

@dhh If we change bundler to automatically generate binstubs when you bundle install, can we revert this commit? The binstubs will be always there, it will be portable and everyone is happy.

@guilleiguaran

Talking with @hone I suggested something like BUNDLE_BIN but outside of .bundle/config (since in this file we can have platform specific configs), in this way will be possible get the binstubs just cloning a repo and running 'bundle install'. wdyt?

@sstephenson
Collaborator

Just wanted to reiterate what @mislav said above—Bundler binstubs with #!/usr/bin/env ruby shebangs work fine with rbenv. The ruby-local-exec shebang is an enhancement that enables you to directly invoke binstubs (from, say, a cron job) without changing to the application directory first.

@wycats
Collaborator

@sstephenson so is it safe to remove the rbenv-specific code from Rails?

@sstephenson
Collaborator

Where is the rbenv-specific code in Rails?

@sstephenson
Collaborator

Yes, strictly speaking it is safe to remove it. Whether or not it's the right thing to do is another matter.

@dhh
Owner
@dhh
Owner

Regardless, this optimization is only triggered for rbenv users. If you are unable to ensure that you can use the same Ruby manager in all envs, just gitignore bin.

@habermann24

The way i do it is like this:

/bin is in version control. Manually add the bins that someone checking out the repo and the production env would need like "rake", "bundle", "unicorn", etc.

Add another directory inside bin: /bin/stubs
and add this directory to gitignore!

Change the line in .bundle/config to:

BUNDLE_BIN: bin/stubs

And be happy :-)

I think this is how 37s handles this aswell (not sure). But i think it's great!! :)

@envygeeks

@habermann24 Why would I want "rake" and "bundle" and "unicorn" from your repository when bundler will bring them in? At that point you might as well throw away your stubs folder and just throw it all into bin and ignore the entire thing. My point is, bin/ should be used for your application specific files... not files and bin/ files from your dependencies.

@kostya

I suggest that 'script/' is a natural place for binstubs, yet from 2.3 rails. And the 'bin/' is a great place to for application-related-bins (bin_script gem). In our project we have hundreds application-bins and don't want mix them with bundler binstubs in bin/.

#7448

@justincampbell

I use binstubs when I use RVM, but I wouldn't want to force other devs on my team to do the same.

Also, I'd like to not have bin/ diffs in my commits. Let bundler take care of that.

@semaperepelitsa

Bundler generates binstubs automatically on bundle install. So what is an advantage of having them checked in?

@envygeeks

@semaperepelitsa you get to make shit hard, and troll people in the process.

@sikachu
Collaborator

@semaperepelitsa just to make sure that you got it right, but currently bundler will only install and regenerate binstubs only if you ran bundle install --binstubs the first time. I'm trying to coordinate with @hone and @josevalim to make sure that we can somehow share the 'regenerate binstubs everytime you run bundle install' setting across the board, since I think that approach is better than checking in ./bin directory, and we don't have to unignore .bundle/.

@nirvdrum

@josevalim @sikachu Auto-generating binstubs isn't fun if you're using multiple rubies for the same project. E.g., trying to make sure it works in both MRI and JRuby.

@sikachu
Collaborator

@nirvdrum it should be fine for you if you're talking about the same machine, since your ruby version manager would manage to make sure that env ruby in the shebang works and point to the right version of Ruby. You would be able to run those binstubs without having to regenerate the ./bin

But the thing is, env ruby is not universal. On some platform, you might require a different shebang line to make those files work. In this case, regenerate the bin every time you run bundle install and .gitignore .bundle/ would be the best solution here, since the first thing you normally do after you clone down the project would be running bundle install anyway. ;)

@edubkendo

There are rails projects that are worked on by groups of people not all working for some company, other orgs where people work from home. Tons of situations and use cases in which forcing everyone to choose rbenv or rvm isn't feasible or even advisable.

@nirvdrum

@sikachu JRuby doesn't ship with a ruby, so the shebang line is different. Using rbenv, it looks like #!/usr/bin/env jruby. Naturally, that won't work for MRI.

@mislav

I'm sad that on Twitter, DHH is trying to dismiss our feedback regarding this change as "nerdrage" about a "single line of code". What I'm seeing in this thread is a civilized debate with many smart people—some of which are high-profile members of our community—raising valid concerns backed up by arguments.

Let's recap. There are two related changes being discussed here:

  1. The ./bin directory is no longer gitignored, signalling that people should check Bundler-generated binstubs in version control;
  2. Rails now detects and special-cases rbenv, resulting in coupling between an application and a ruby version manager.

Even if the changes to Rails are technically small, the repercussions of these changes are not to be dismissed. Rails defaults are important because they teach us how Rails expects the majority of us to use it.

  1. Versioned binstubs are potentially non-portable (especially when coupled to rbenv), and it makes no sense having them under version control since every user needs to run bundle anyway & can choose to get the binstubs (especially with the potential improvement that @sikachu mentioned).

  2. rbenv detection is flawed (just detects rbenv being present on the system, not actually used) and introduces a coupling that both requires that everyone on the team and the deployment environment should use the same version manager, and results in binstubs breaking after a switch to another ruby version manager.

Also, during this discussion we've received input from notable figures:

  1. The author of Bundler expressed his disapproval of Bundler-generated binstubs getting version-controlled;
  2. The author of rbenv said that the coupling with rbenv is not necessary;
  3. An employee of Heroku is concerned about people's apps not functioning anymore on their platform;
  4. At least 3 Rails Core team members are participating, not happy with the change and proposing alternatives.

But somehow, DHH is still dismissing their opinions and ridiculing the participants of this thread that they are wasting their breath.

So my question is, if Rails' own core team and authors of popular tools/platforms that Rails depends/runs on can't influence a change to the framework, is "opinionated" still a motto we should stand behind?


**Update:** I forgot to state the most important reasons why I think these changes are harmful.

They are harmful because it teaches wrong usage of 3rd party tools such as Bundler and rbenv. As a maintainer of rbenv, I'm going to be sad when newcomers to Ruby/Rails experience problems with ruby-local-exec, start googling and discover that this comes from a project called rbenv and will think that is the source of their woes. Same goes for Bundler. Same for Heroku.

@sikachu
Collaborator

@nirvdrum I apologize, I didn't know that rbenv would set that shebang line to jruby since I looked at mine it seems like they got set to env ruby_nonexec_wrapper, which comes with bundler, and later then have a shebang line to env ruby

[~] ruby -v
jruby 1.7.1 (1.9.3p327) 2012-12-03 30a153b on Java HotSpot(TM) 64-Bit Server VM 1.6.0_37-b06-434-11M3909 [darwin-x86_64]
[~] head `which rails`             
#!/usr/bin/env ruby_noexec_wrapper
#
# This file was generated by RubyGems.
#
# The application 'rails' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

[~] head `which ruby_noexec_wrapper` 
#!/usr/bin/env ruby

original_file=ARGV[0]
ARGV.shift
$PROGRAM_NAME=original_file

require 'rubygems'
begin
  require 'rubygems-bundler/noexec'
rescue LoadError
[~] 
@sikachu
Collaborator
[~] which ruby
/Users/sikachu/.rvm/rubies/jruby-1.7.1/bin/ruby
[~] env ruby -v
jruby 1.7.1 (1.9.3p327) 2012-12-03 30a153b on Java HotSpot(TM) 64-Bit Server VM 1.6.0_37-b06-434-11M3909 [darwin-x86_64]
[~]

So I was assuming that regardless of the MRI/JRuby, env ruby will return the Ruby interpreter for you.

@whalesalad

To be honest this entire thread is indicative of a larger issue: bundler's binstubs. Without getting into too much detail: wouldn't it just make more sense to have your $PATH modified dynamically for each project you are working on? Then we can avoid the bundle exec // binstubs issue altogether. And, I agree, this is something that should not be in version control.

I'm fairly new to the Rails world and come from Python/virtualenv. While I much prefer the Rails way for 99% of things, virtualenv was pretty radical. Over yonder, we would create a virtual environment that had it's own version of Python, it's own place for 'gems' (referred to the site-packages directory in Python). It provides an interface to 'workon' a project (the command is called workon) which loads up that virtual environment. All it really does is modify your PATH. In this way, Python itself, it's libraries, third party libraries, etc... are all isolated to that one single root directory. And each developer has their own virtualenv so they can use slightly different tools if they'd like, without causing problems for anyone else on the team.

@krainboltgreene

Stop talking about this as a Bundler/binstubs/platform/ruby env issue.

It should not be the Rails default to version control bin/. Only in specific, probably wrong, cases should you want to do that.

This is absolutely an opt-in choice, not an opt-out.

How is this still not reverted?

@ddd

So DHH saying: "Regardless, this optimization is only triggered for rbenv users. If you are unable to ensure that you can use the same Ruby manager in all envs, just gitignore bin." and deciding to leave in rbenv specific 'conventions' in Rails is all about ensuring rails handles rbenv and its requirements, not about a design decision good for the Rails community as a whole! Ahhh, gotcha! Thank you for the clarification.

So, rails community, standardize on rbenv only, rails will ensure that your project is correctly configured for its requirements (.gitignore so that rbenv scripts don't blow up, or have to cd to the project dir first in scripts), and anyone else using any other ruby managers, You're Doing It Wrong! (Tm) per DHH.

Good to know. Love the community awareness and caring!

@sikachu
Collaborator

I know that people are frustrated about @dhh decision on this, and the fact that this doesn't get reverted yet — I do too. However, let's not trying to make this into another drama. I think everyone clearly stated their point as @mislav has summarized it.

@dhh, from everything we just said, would you mind revert this and maybe we can figure out a better solution together?

@hmans

FWIW, I've always wondered why rails new runs bundle install by default. Yes, I know you can disable it using the --skip-bundle flag. I also know that if you're unhappy with the Bundler defaults coming with Rails, you can just rm -rf .bundle and invoke it with whatever settings please you.

However, looking at the above discussion, wouldn't it be wiser to simply not invoke Bundler by default and leave that up to the developer setting up their new application/the newly cloned repository?

@sethvargo

I want to reiterate this from @mislav:

Also, during this discussion we've received input from notable figures:

  1. The author of Bundler expressed his disapproval of Bundler-generated binstubs getting version-controlled;
  2. The author of rbenv said that the coupling with rbenv is not necessary;
  3. An employee of Heroku is concerned about people's apps not functioning anymore on their platform;
  4. At least 3 Rails Core team members are participating, not happy with the change and proposing alternatives.

Yes, it's an organizational problem if all developers can't share the same development environment, but I really don't think Rails should be making that decision for an organization.

  1. Young startups may not be able to afford all the same equipment for employees or virtualization. Furthermore, Rails has always been a "hit-the-ground-running" framework. This change increases the probability of merge conflicts 10-fold.

  2. Older companies with technical debt may rely on legacy systems (cough Oracle) that don't work on new development machines (cough OSX Mountain Lion). The binstubs that get compiled against Mountain Lion are different for a lot of gems.

While I agree that it's an organizational problem to have differing development environments, its also a problem that Rails shouldn't be making the decision.

@dhh write another book if you want to fix organizations, don't break Rails.


Now, let me give you a real use case - education. I'm the head teaching assistant for an Application Design and Development course at Carnegie Mellon. We use rails to teach students principles like MVC, database abstraction, and web apps in general.

They use their own personal laptops

That means we have to support Windows, Linux, Mac OS (Leopard - Mountain Lion), CentOS, and pretty much any other platform. They work in teams and pair program for many parts of their assignments and phase reports. I'm pretty sure it's not even possible to share binstubs (for many gems) between Windows and Linux.

Possible solutions:
1. Make everyone use vagrant
2. Make everyone buy a brand new Mac (ha!)
3. Have everyone gitignore bin

OR

Listen to the very highly-regarded authors and community members and ignore binstubs.

The argument:

Also, if you really do insist, you can always add this to .gitignore yourself.

goes the other way too: You can always force add those files with git :smiley:

@jrgifford

The education part of this is very big. I had a class of 3 last summer (small classes of beginners is good), and we had three different operating systems present - Windows 7, Windows XP and a Linux install. I'll confuse my next group of students even more when I have to get up and say "Because of how rails does things, you have to do a lot of different hoops just to get the basic application that we'll be dissecting to run."

Particularly when I just finished telling them how awesome rails is for having sane defaults, and how awesome ruby is for 99% of the time not caring about what OS you're running.

@sethvargo

@jrgifford Rails is a major player in education, and I think that often goes overlooked. It's a great starting place for beginner programmers (half because Ruby is awesome and half because Rails has had sane defaults).

@agmcleod

Don't want to beat the dead horse here, but I just want to add that myself and another are working on a small project. His mac died, and it's not really practical for him to buy a new mac right now, so he was considering getting the rails app going on his windows machine. Something like this could cause a nasty headache to many who don't always check the gitignore, when really it benefits so few, and adds a very small convenience to a well organized team. So many people in here are concerned, and would have to configure their initial rails setup to ignore the bin stubs.

@bronson

@dhh if rbenv is the only Ruby selection tool endorsed by Rails then why not just say so? Your passive approach is generating insane amounts of discussion.

@jaroslawr

I don't care about the .gitignore, but why is there now a dot at the end of each comment except one?

@gafterbot

a bunch of thin-skinned pansies. count yourself lucky dhh didn't gafter anyone as he reverted the change.

this is what he should have written:

Dozens of language framework "proposals" are now generated weekly by people incompetent to the task. Sometimes the author is quietly tolerated by the community until their attention to the issue wanes. Sometimes a more persistent author attempts to pursue their proposal, and eventually comes to realize that they are out of their depth. Occasionally an individual with a complete lack of talent never comes to appreciate the futility of their approach, and attempts to recruit support from a wider community of amateurs.

@ddd
@dhh
Owner

Without engaging in the nerd-rage fest, here's a summary of the intentions that all the people who are actually willing to get into the kitchen have signed on with:

/u/apps/example/bin/rake should run the rake from /u/apps/example/Gemfile.lock, use the ruby declared in /u/apps/example/.rbenv-version (or .ruby-version), and not care whether it's run from the app directory or not (so no need to cd in a cron command). These binstubs should be available for the major tools like rake, rails, bundle, and cap by default and require no configuration to setup. They should strive to be as cross-platform as possible.

That's the mission and we have some great contributors working on making it so.

Feel free to keep the festival going, though. No reason to stop just because software is being made in the background.

@sethvargo

@dhh you've failed to address any of @mislav's points + the concern for using rails as an educational tool.

@dhh
Owner

@sethvargo Mislav is part of the team making it work.

@jeremy
Owner

Your app's ./bin dir will be where executables live: rails, bundle, rake, cap, etc. That'll "just work" in dev and production. Bundler will install binstubs selectively: you pick what you want.

Heroku is on board :heart: Bundler is on board :heart: rbenv is on board :heart: Rails is on board :heart:

@krainboltgreene

Well I definitely feel like I've been heard and that my point has been well received. No way have I been insulted at all.

@mislav

I'm glad for how it turned out. There were some harsh words thrown around, but let's not focus on that. The main thing to know is that people are working on addressing these issues; so our voice was heard after all.

The reason why the decision process is not transparent enough is because Rails Core prefers to discuss issues in their private chat room instead of here on GitHub.

@brookr

Thanks, everybody! This tour of the sausage factory was highly informational and entertaining.

@pmarreck

Our team has rbenv devs and rvm devs, comfortably working side by side, like sheep and wolves lying together. Nobody told us until now that it was madness, so I fear a sudden predator-prey conflict is about to emerge... Thanks a lot, DHH! ;)

@mcmire

I'm not going to even touch the drama, because we all have opinions. But there's a question no one really asked, which is: What was the motivation behind this? I'm not judging, I just want to be in the know. Was it to make something easier? Was it to incorporate a little more of Bundler into Rails? Was it to codify a common pattern that you 37signalers use? Was it to combine script/ with bin/? What is the future plan here... that's all I want to know.

@dhh
Owner
@semaperepelitsa

@DHH, what is the reason to check binstubs in source control? You still have to run bundle install which generates binstubs automatically.

@pixeltrix
Owner

@mcmire specifically this comment.

@dhh
Owner
@krainboltgreene

Of course, not everyone is king of Rails and thus irrevocable change access to rails/rails, and so the rest of just make binstub generation a part of the build process.

Crazy world.

@semaperepelitsa

@DHH, it does if you add the option to the global config (~/.bundle/config). You can also specify shebang there suitable for your machine. These settings aren't project specific, are they?

@dhh
Owner
Please sign in to comment.
Something went wrong with that request. Please try again.