Revisions
-
glv revised this gist
Dec 27, 2013 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -150,12 +150,12 @@ Both of these methods update `Gemfile.lock`, so the production system and all of your colleagues will end up with the exact same mix of versions you tested with. (A quick note, thanks to Mark McSpadden: if you ever accidentally type `bundle install something` instead of `bundle update something`, Bundler will install *all* of your gems in a directory called "something" and reset things so that *that's* your project gem repository. Why? Because `bundle install something` is an old, deprecated syntax for `bundle install --path something`. If this happens, just remove the new `something` directory, type `bundle install --path .bundle`, and you're back in business, having lost nothing but a bit of time. Just try not to accidentally type `bundle install app`.) -
glv revised this gist
Dec 27, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -28,7 +28,7 @@ If you like terse, go type `bundle help update` instead.) **Step 1: Configuring Bundler** Right now, run `bundle config path .bundle` from your home directory.<sup><a href="#footnote1">1</a></sup> <sup><a href="#footnote2">2</a></sup> This adds a line to your user-global bundler configuration file (`~/.bundle/config`). The effect is that `bundle install` will always run as if you'd specified the `--path .bundle` option. What does that do? It tells Bundler not to install gems in your default gem repository (whether that's a gemset or not); -
glv revised this gist
Aug 16, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,7 +23,7 @@ First, the quick summary: The rest of this section is a longer version, explaining the rationale. (This is essentially the same as the "Recommended Workflow" in the bundler-update man page, but not as terse. If you like terse, go type `bundle help update` instead.) **Step 1: Configuring Bundler** -
glv revised this gist
Aug 16, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -190,4 +190,4 @@ but using them differently in those two distinct circumstances just feels right YMMV. <a name="footnote4"></a> <sup>4</sup> Just last week (as of 2013-08-16) a colleague said "I always thought of bundle exec as a hack ... as in, 'Oh, gems are messed up, just run bundle exec'". The truth is that if you *aren't* running `bundle exec`, gems are *always* messed up; you're just not seeing visible symptoms. Using the strategy recommended here (especially if you go all the way and abandon gemsets) ensures that if you aren't using `bundle exec` things will fail fast, rather than seeming to work and hiding the problems. -
glv revised this gist
Aug 16, 2013 . 1 changed file with 8 additions and 5 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -97,7 +97,7 @@ This way, when you install some gem-based programming tool it's useful everywhere, not just in the projects where you've remembered to install it. Of course, you will have to install it for the different *Ruby* versions you use. And that also means we can get rid of stuff like this snippet from the Gemfile of one of our projects: ```ruby # dev utilities @@ -108,16 +108,16 @@ end At least some of those gems are developer preferences, not project dependencies. If you like the "cheat", "hirb", and "open_gem" gems, they should be available everywhere on your system, not just in the gemset for that project. Just `gem install` them! Finally, and most importantly, Bundler will behave better for you. You will have to use `bundle exec` for things like rake and resque-web, but you should have been doing that anyway. I'm not just being pedantic when I say that. If you were able to run those commands without `bundle exec`, you were just getting lucky, and some flaky, strange things were probably happening. Sooner or later, it would fail in confusing ways.<sup><a href="#footnote4">4</a></sup> There are multiple ways to make `bundle exec` easier. I use a smart Bash function that wraps certain commands and figures out what to do. @@ -187,4 +187,7 @@ Because, based on the description I just gave of what `bundle install` does, I think it's misnamed, and so using `bundle install` for minor updates messes with my mental model. I know the two ways of invoking the "install" subcommand do the same thing, but using them differently in those two distinct circumstances just feels right to me. YMMV. <a name="footnote4"></a> <sup>4</sup> Just last week (as of 2013-08-16) a colleague said "I always thought of bundle exec as a hack ... as in, 'Oh, gems are messed up, just run bundle exec'". The truth is that if you *aren't* running `bundle exec`, gems are *always* messed up---you're just not seeing visible symptoms. Using the strategy recommended here (especially if you go all the way and abandon gemsets) ensures that if you aren't using `bundle exec` things will fail fast, rather than seeming to work and hiding the problems. -
glv revised this gist
Aug 16, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -65,7 +65,7 @@ That means first resolving any changes you made to `Gemfile`, and making the minimal necessary changes to `Gemfile.lock` to reflect those changes. Then it installs, upgrades, or removes any gems necessary to make your project gem repo match what's specified in `Gemfile.lock` exactly. If you're the one who made the change to the Gemfile, you'll need to run `bundle` (or `bundle install`, if you prefer being explicit).<sup><a href="#footnote3">3</a></sup> But if someone else made the change and you just pulled it down, you can run `bundle --local`. The gems will all be cached in `vendor/cache` within the project, and `bundle --local` simply uses the cached files and avoids the time-consuming calls to rubygems.org and other gem sources. If in doubt, you can just run `bundle --local`; if the right gems aren't in `vendor/cache` it will fail quickly, and then you can run the more time-consuming `bundle`. **Step 4: Consider abandoning gemsets** -
glv revised this gist
Aug 16, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -65,7 +65,7 @@ That means first resolving any changes you made to `Gemfile`, and making the minimal necessary changes to `Gemfile.lock` to reflect those changes. Then it installs, upgrades, or removes any gems necessary to make your project gem repo match what's specified in `Gemfile.lock` exactly. If you're the one who made the change to the Gemfile, you'll need to run `bundle` (or `bundle install`, if you prefer being explicit).<sup><a href="#footnote3">3</a></sup> But if someone else made the change and you just pulled it down, you can run `bundle --local`. The gems will all be cached in `vendor/cache` within the project, and `bundle --local` simply uses the cached files and avoids the time-consuming calls to rubygems.org and other gem sources. If in doubt, you can just run `bundle --local`; if the right gems aren't in `vendor/cache` it will fail quickly, and then you can run the more time-consuming `bundle`.<sup><a href="#footnote3">3</a></sup> **Step 4: Consider abandoning gemsets** -
glv revised this gist
Aug 16, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,7 +15,7 @@ Give it a try. First, the quick summary: 1. Run `bundle config path .bundle` from your home directory<sup><a href="#footnote1">1</a></sup> <sup><a href="#footnote2">2</a></sup> 2. Run `bundle install` in all of your projects 3. Always run `bundle` (*not* `bundle update`) unless you're explicitly upgrading gem versions. -
glv revised this gist
Aug 16, 2013 . 1 changed file with 13 additions and 12 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,7 +27,7 @@ If you like terse, go type `bundler help update` instead.) **Step 1: Configuring Bundler** Right now, run `bundle config path .bundle` from your home directory.<sup><a href="#footnote1">1</a></sup> <sup><a href="#footnote2">2</a></sup> This adds a line to your user-global git configuration file (`~/.bundle/config`). The effect is that `bundle install` will always run as if you'd specified the `--path .bundle` option. What does that do? @@ -65,16 +65,7 @@ That means first resolving any changes you made to `Gemfile`, and making the minimal necessary changes to `Gemfile.lock` to reflect those changes. Then it installs, upgrades, or removes any gems necessary to make your project gem repo match what's specified in `Gemfile.lock` exactly. If you're the one who made the change to the Gemfile, you'll need to run `bundle` (or `bundle install`, if you prefer being explicit). But if someone else made the change and you just pulled it down, you can run `bundle --local`. The gems will all be cached in `vendor/cache` within the project, and `bundle --local` simply uses the cached files and avoids the time-consuming calls to rubygems.org and other gem sources. If in doubt, you can just run `bundle --local`; if the right gems aren't in `vendor/cache` it will fail quickly, and then you can run the more time-consuming `bundle`.<sup><a href="#footnote3">3</a></sup> **Step 4: Consider abandoning gemsets** @@ -186,4 +177,14 @@ and you'll be in good shape. <sup>1</sup> RubyMine (4.0.x) doesn't see `.bundle` and will nag you about missing gems and won't allow you to browse the source of them. If you use RubyMine, instead of `.bundle` you'll need to use a directory name that doesn't start with a dot, such as `gems` (or perhaps `zzgems` to force search hits to the bottom of the results). If you do this, be sure to add `gems` or `zzgems` to `.gitignore` in your home directory, so you don't accidentally check your bundle in. <a name="footnote2"></a> <sup>2</sup> If you are a frequent user of ack, you may now start seeing search results from your gems. If you'd like to avoid seeing this output, add `export ACK_OPTIONS=--ignore-dir=.bundle` to your bash config file. Happy ACKing! <a name="footnote3"></a> <sup>3</sup> When I'm getting started with a new project, I always type `bundle install`, but then for the rest of the life of that project I type `bundle`, even though they do the same thing. Why? Because, based on the description I just gave of what `bundle install` does, I think it's misnamed, and so using `bundle install` for minor updates messes with my mental model. I know the two ways of invoking the "install" subcommand do the same thing, but using them differently in those two distinct circumstances just feels right to me. YMMV. -
glv revised this gist
Jul 15, 2013 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ # Trouble-Free Bundler Every couple of weeks, I hear someone complaining about some difficulties with Bundler. Yesterday, it happened twice. -
glv created this gist
Jul 15, 2013 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,189 @@ (Originally by Glenn Vanderburg) Every couple of weeks, I hear someone complaining about some difficulties with Bundler. Yesterday, it happened twice. But somehow I just never have those difficulties. I'm not saying Bundler is perfect; certainly in its early days it wasn't even close. But for the past two years it's been incredibly solid and trouble-free for me, and I think a large part of the reason is the way I use it. Bundler arguably does too much, and just as with Git, a big part of it is knowing what *not* to do, and configuring things to avoid the trouble spots. ## My Strategy This is my strategy for using Bundler, and for me it's always been smooth sailing. Give it a try. First, the quick summary: 1. Run `bundle config path .bundle` from your home directory<sup><a href="#wiki-footnote1">1</a></sup> <sup><a href="#wiki-footnote2">2</a></sup> 2. Run `bundle install` in all of your projects 3. Always run `bundle` (*not* `bundle update`) unless you're explicitly upgrading gem versions. 4. Optionally, stop using gemsets. The rest of this section is a longer version, explaining the rationale. (This is essentially the same as the "Recommended Workflow" in the bundler-update man page, but not as terse. If you like terse, go type `bundler help update` instead.) **Step 1: Configuring Bundler** Right now, run `bundle config path .bundle` from your home directory.<sup><a href="#wiki-footnote1">1</a></sup> <sup><a href="#wiki-footnote2">2</a></sup> This adds a line to your user-global git configuration file (`~/.bundle/config`). The effect is that `bundle install` will always run as if you'd specified the `--path .bundle` option. What does that do? It tells Bundler not to install gems in your default gem repository (whether that's a gemset or not); rather, Bundler will create a project-specific gem repository in the `.bundle` directory and manage gems there. This is an example of what Bundler calls "remembered option"—it's a sticky setting. Bundler remembers that you asked for a project-specific gem repository for this project, so any future bundler commands in the project will automatically operate within `.bundle`. **Step 2: Updating projects to obey the new configuration** Now go run `bundle install` in all of your projects. **Step 3: How to handle Gemfile changes** Never run `bundle update`. (Well, almost never ... see below.) Instead, whenever you update the Gemfile, or when Bundler tells you a gem is not found, just type `bundle`. What's the difference? `bundle update` ignores `Gemfile.lock`. It looks at *all* of the project's gems and updates them to the latest, supposedly greatest versions that are compatible with the specified version constraints and that satisfy all of the transitive dependencies, and then regenerates `Gemfile.lock`. Even if the project has carefully locked down all of the Gem versions in `Gemfile`, this can result in upgrading some of those gems' dependencies, which is both a nuisance (because now everyone on the project has to go through a more time-consuming update of multiple gems) and dangerous (because it will happen in production as well, and one of those upgrades could break something). In contrast, `bundle` is the same as `bundle install`, which honors `Gemfile.lock`. The job of `bundle install` is simply to make the smallest number of changes necessary to make everything consistent. That means first resolving any changes you made to `Gemfile`, and making the minimal necessary changes to `Gemfile.lock` to reflect those changes. Then it installs, upgrades, or removes any gems necessary to make your project gem repo match what's specified in `Gemfile.lock` exactly. If you're the one who made the change to the Gemfile, you'll need to run `bundle` (or `bundle install`, if you prefer being explicit). But if someone else made the change and you just pulled it down, you can run `bundle --local`. The gems will all be cached in `vendor/cache` within the project, and `bundle --local` simply uses the cached files and avoids the time-consuming calls to rubygems.org and geminabox.lsqa.net. If in doubt, you can just run `bundle --local`; if the right gems aren't in `vendor/cache` it will fail quickly, and then you can run the more time-consuming `bundle`. (Aside: when I'm getting started with a new project, I always type `bundle install`, but then for the rest of the life of that project I type `bundle`, even though they do the same thing. Why? Because, based on the description I just gave of what `bundle install` does, I think it's misnamed, and so using `bundle install` for minor updates messes with my mental model. I know the two ways of invoking the "install" subcommand do the same thing, but using them differently in those two distinct circumstances just feels right to me. YMMV.) **Step 4: Consider abandoning gemsets** Now, if you'd like, you can stop using gemsets and get rid of all of them. I recommend that you give it a try. How do you do that, when every project's `.rvmrc` file instructs RVM to create and use a gemset? I did it by switching to rbenv (and I didn't install rbenv's gemset plugin). If you want to stick to RVM, do this: ```bash echo "export rvm_ignore_gemsets_flag=1" >> ~/.rvmrc ``` and then exit your shell and restart (or whatever it is you do to get RVM to reload its configuration). You don't *have* to stop using gemsets. If you do just the first three steps, but decide to continue using gemsets for your own purposes, that's great and things will work fine. But if your big reason for using gemsets had to do with managing bundler, or keeping project dependencies separate, you don't need them anymore. ## The Benefits A clean separation between "the project's gems" and "my gems" is a big win. This way, when you install some gem-based programming tool (such as Nick's "jsonpretty" or Evan's "gx") it's useful everywhere, not just in the projects where you've remembered to install it. Of course, you will have to install it for the different *Ruby* versions you use. And that also means we can get rid of stuff like this snippet from Deals' Gemfile: ```ruby # dev utilities %w[ cheat foreman hirb lunchy open_gem ruby-debug ruby-prof wirble yard ].each do |name| gem name end ``` At least some of those gems are developer preferences, not project dependencies. If you like the "cheat", "hirb", and "open_gem" gems, they should be available everywhere on your system, not just in the Deals gemset. Just `gem install` them! Finally, and most importantly, Bundler will behave better for you. You will have to use `bundle exec` for things like rake and resque-web, but you should have been doing that anyway. I'm not just being pedantic when I say that. If you were able to run those commands without `bundle exec`, you were just getting lucky, and some flaky, confusing things were probably happening. Sooner or later, it would fail in confusing ways. There are multiple ways to make `bundle exec` easier. I use a smart Bash function that wraps certain commands and figures out what to do. Alternatively, you can use Bundler's binstubs (which is a whole 'nuther article). ## Upgrading Gems One more thing: above, I said you should almost never run `bundle update`. But clearly, we do have to update gems, and we should do it fairly regularly, because it's easier to upgrade if you follow along, as opposed to lagging behind and then someday being forced to upgrade from a seriously out-of-date gem. So what should you do? If you lock down your `Gemfile` to explicit versions, you can just update the version of a selected gem in `Gemfile` and then run `bundle`. That will make the smallest number of upgrades necessary to bring that gem to the requested version. Then you can test and, if all seems well, commit and deploy. My preferred method is to *not* lock things down too tightly in `Gemfile`. Then, when I want to try upgrading a gem (let's use the "chronic" gem as an example) I'll type `bundle update chronic`. Bundler will update just that gem to the latest version. (It might have to also update some of chronic's dependencies, but that will be true in either case.) Then, if testing doesn't uncover any problems, I can commit and deploy. This method, by the way, only works if nobody on the team ever uses `bundle update` *except* when explicitly trying to upgrade out-of-date gems. But that's the right way to use it anyway, and it's easy to catch and recover from mistakes. In either method, you only upgrade gems when you choose to. Both of these methods update `Gemfile.lock`, so the production system and all of your colleagues will end up with the exact same mix of versions you tested with. (A quick note, thanks to Mark McSpadden: if you ever accidentally type `bundle install chronic` instead of `bundle update chronic`, Bundler will install *all* of your gems in a directory called "chronic" and reset things so that *that's* your project gem repository. Why? Because `bundle install something` is an old, deprecated syntax for `bundle install --path something`. If this happens, just remove the new directory, type `bundle install --path .bundle`, and you're back in business, having lost nothing but a bit of time. Just try not to accidentally type `bundle install app`.) ### Backing Out of a Gem Upgrade What if something goes wrong? The upgrade might break something that didn't show up in your testing. If that happens, simply check out the most recent versions of `Gemfile` and `Gemfile.lock` that were working correctly, run `bundle`, and deploy. You'll be back to the exact same gem version mix that was working before. Note that simply reverting the commit where you upgraded gems will have the desired effect. If you find problems right away, before committing the changes, just do `git checkout Gemfile Gemfile.lock && bundle` and you'll be in good shape. --- <a name="footnote1"></a> <sup>1</sup> RubyMine (4.0.x) doesn't see `.bundle` and will nag you about missing gems and won't allow you to browse the source of them. If you use RubyMine, instead of `.bundle` you'll need to use a directory name that doesn't start with a dot, such as `gems` (or perhaps `zzgems` to force search hits to the bottom of the results). If you do this, be sure to add `gems` or `zzgems` to `.gitignore` in your home directory, so you don't accidentally check your bundle in. <a name="footnote2"></a> <sup>2</sup> If you are a frequent user of ack, you may now start seeing search results from your gems. If you'd like to avoid seeing this output, add `export ACK_OPTIONS=--ignore-dir=.bundle` to your bash config file. Happy ACKing!