RubyConf 2017: A History of Bundles: 2010 to 2017 by André Arko


(upbeat piano music) – Hi everybody. Let’s get started. Man, I really can’t see any of you. This is super glary stage. Okay, so. This is my talk. (laughing) So when Bundler came out in 2010 or whenever it finally came out, it did something really cool. It installed your gems, and it let you use those
gems in your application. It was great. Today, Bundler does something really cool. It installs your gems and lets you use them in your application. Still pretty great. But, in the eight-ish years since then, Bundler has needed thousands
and thousands of hours of development work. And it’s maybe not super
clear to most people why that was necessary if the starting point and the
ending point are so similar. So kind of what happened
between then and now is mostly what this talk is about. Before we dive into that, let me at least introduce myself. I’m Andre Arko. I go by indirect on the internet things. That’s the tiny picture of my head that shows up next to
commits and GitHub issues. I work at Cloud City doing Ruby on Rails consulting. Mostly that means that I
join teams at other startups that are already doing
web development work and kind of like participate in the team as a senior dev and make suggestions and architect things. Totally hit me up if that’s something that your company would like. I also wrote a book. I’m super fond of this book
and I keep talking about it because it makes me really happy that I learned Ruby from
The Ruby Way First Edition in like the early 2000s. And I got to update The Ruby Way for the modern Ruby world. I think the third edition covers up through Ruby 2.3. So it’s even kind of
relatively still up to date which is cool. My other company is Ruby Together. Ruby Together takes funds
from companies that use Ruby and uses those funds to
pay for development work on Ruby open source, like Bundler and RubyGems. I will talk a little bit more about that as we get to that part of the history. But of course, the reason why you’re here
for this talk is Bundler. I’ve been on the Bundler
team since 2009-ish, and I’ve been the lead
developer since 2012-ish. And so in this talk, it’s going to be kind of a
combined historical retrospective and walkthrough for
Bundler’s advanced features which were almost all added after 1.0 came out as we discovered things that people needed or cool things that you could do. So by the end of this talk, hopefully, you’ll have a better understanding of why Bundler has needed so
much development over time, exactly what we managed to do
with all of that development, and know about some of
the cool Bundler features that you can use to do fancy
and complicated things. So, here we go. When Ruby was first released, sharing code with other developers meant copying files that ended in dot R-B and then using require, maybe after having edited
the load path variable. It was a lot of work. There was no idea about versions except maybe if you put
a comment in the file and said this file is version something. It was not great. Later, Jim Weirich and Chad Fowler, who just gave the keynote last night, and Rich Hickey worked together and created RubyGems. And with RubyGems, you could install things
with just one command, which was super great. It was so much better
than downloading tarballs from people’s websites. It was so good. And after a few years, we noticed that installing gems was easy, but changing the gems that you were using after you’d written code that used them was really hard. And this is not obvious up front when you’re like oh my god,
I installed this gem so fast. And then three years later you’re like oh my god, I installed the gem
and it was the wrong version, and I couldn’t tell why my
application didn’t work. So this caused a lot of pain where installing gems would sort of suddenly and unexpectedly
give you different code than you thought you were going to get. And it meant that very briefly, the most popular approach
to having dependencies was to take all of the gems, put them in your
application’s Git repository and commit them. Which, please don’t do that. It’s a really bad idea. But for a while, that felt like the only way that you could put your app on another machine and actually be confident
that it would run. So, there’s actually a lot more details about that kind of history in an entire talk that I
gave a couple years ago at RubyConf called How
Does Bundler Work, Anyway? It’s pretty great actually to kind of realize the context
that Bundler came into and solved the problem of if that wasn’t something
that you had to live through. Made me really happy anyway. So despite being used in
nearly every Ruby application and script today, Bundler was developed in response to a super specific developer need originally which was web applications
that have tons of dependencies. When Bundler was first prototyped, it meant web applications
that were written in a no longer existent Ruby
framework called Mirb. Mirb had like kind of
pioneered this idea of splitting up your framework
into lots of tiny gems so that you didn’t have
to use the whole thing. Rails at that point was still
only like five gems total. And so Bundler was needed super badly when Mirb was like oh there’s 20 gems, and now you have to make
all of them work together. And as time went on, Mirb and Rails teams agreed to merge. Bundler kind of switched from
targeting Mirb applications to targeting Rails Three applications. And Bundler existing meant that Rails apps can now kind of like out of the box need dozens of gems rather
than just needing four, and life is still okay. So, there were like two specific insights that drove the development
of Bundler as a tool. The first insight was that you needed an install-time dependency resolver, which was not a thing that Ruby had. And the second insight was
that the resolution process needed to produce a lockfile so that you could reuse the
results of that resolution on other machines as you went to install that application on a new developers box, or on the next server you spun up, or whatever. So, what is a dependency resolver? It takes a list of gems that you ask for, asks those gems for the
gems that they need, asks those gems for the
gems that they need, etc. And eventually, it has a
complete list of every gem that you could need. And then it checks every gem’s
list of version requirements to make sure that they all fit together. For example, something depends on Rack 1.0, something else depends
on Rack less than 2.2. And those requirements are compatible. Like Rack 1.1.1 works. But you have to do a bunch
of work to figure that out and be sure that that’s true. So, how about install-time? Well, if you do your dependency resolution while you’re installing gems, it means that you know in advance whether your application
can actually start up. And if you do dependency
resolution at run-time, you start requiring gems
and everything seems great until you hit something
that isn’t compatible, and then your application crashes. Less than ideal. As you can probably imagine, finding out about these problems before your application starts up is a large improvement. So, third thing, how about the lockfile. So that just means that we, after figuring out the
list of gems and versions that actually can work
together without crashing, we write it down in a file and those gem names and version numbers together make up the bundle that gives Bundler its name. Amazing. (audience laughing) Installing and running Ruby software in a deterministic and repeatable way on different computers is basically the entire rationale
for Bundler’s existence. So, all of that tooling comes together. And it’s… pretty recognizable, even across the ten years
that this project has existed. You put your gems in a gem file, you run bundle install, your gems show up, you have a lockfile, you bundle exec something to make sure that you’re using the right version. Pretty cool. At the time, a super nice new feature way back then was the idea of being able to use gems straight out of Git repositories, which was not possible before
Bundler let you do that. Using a gem that… Forking a gem and making changes to it before Bundler allowed Git repository gems was a gigantic, unbelievable hassle. You had to like fork the repo, make your changes, build a new gem, put it somewhere you could install it, maybe change the name, maybe give it a weird version number so that it didn’t conflict with one of the public version numbers. It was a giant hassle. Bundler made it way better. Another new thing that happened
was the bundle gem command so that you could make gems that worked inside Git repos with Bundler. At the time that Bundler came out, the most popular gem creation thingy was Jeweler. But Jeweler made gems that
didn’t work in Git repositories. So we were like oh no, we have to do something so
that this all works together. Bundler also makes managing gems easier. So I guess today it might feel kind of
obvious and natural to use Bundler to manage your gems. But at the time, it was really, really, I cannot stress this enough, really controversial to use
Bundler to manage your gems. And the entire concept of Bundler was really met with a lot of resistance by kind of like existing
very experienced devs who were like well we already
have our crappy workaround for how to make sure that we can install gems somewhere else. I’m not really sure why I
would want to use this tool that has a different workflow
that I don’t know yet. Really, like the entire
Bundler team spent months just like typing furiously on the internet telling people no, really, Bundler is actually good. And this talk that I gave
at RailsConf in 2010, the first slide is Why Bundler? Like I actually had to convince people that Bundler was a good idea in 2010. And it was a lot of work to do that. Fortunately, within a couple years, people actually used Bundler, and eventually they were like oh, actually this is really great. And so, Bundler was kind of like a really popular, mostly used by most devs tool. And then once people started using it, we immediately had new
things to argue with people on the internet about like why is it so slow? So… At this stage, it was kind of like, no one is arguing that
Bundler is a bad idea anymore. Now it’s just people saying okay fine, it’s a good idea but
I don’t want to use it because bundle install
takes millions of years. And that makes me not want to use it. So part of that was because
just making Bundler 1.0, we had been very focused
on making it actually work. We rewrote Bundler like completely different UI, different commands, different internal implementation of how the bundle worked
like three times in a row. Like 0.8, 0.9, 1.0. And so when we shipped 1.0, we were mostly just really
excited that it actually worked. And on top of that, when Bundler first came out, there weren’t any giant
five year old applications with 750 gems using Bundler because it was brand new. And so like as Bundler got more popular, either applications grew over time until they had tons of gems, or people started retrofitting Bundler onto their old applications that already had tons of gems. And we suddenly wound up in this state where we were like wait, you have how many gems
in your application? Are you serious? And I can say with absolute certainty that when we shipped Bundler 1.0, we could not have imagined
that there would be a single application with 600 gems. And that is not that uncommon today. Sadly, for totally unrelated reasons, you might think that since
installing big applications was really slow that installing small
applications would be really fast. Also not true. (audience laughing) Even if your gem file
only had one gem in it, Bundler still had to download a list of every single gem in existence just to make sure that
it knew about the gem that you were going to install. As you can imagine, downloading that list
maybe took some time. It really takes a long time. And so we were in this place where small gem files were slow to install because of downloading
more data than we needed. And big gem files were slow to install because we had literally never imagined you would install hundreds
and hundreds of gems in one bundle install. And so we hadn’t optimized it at all. So this is about the time where the Bundler team was
sitting around saying, Man, this really sucks that we have to download
so much data all the time. And then Nick Quaranto was just like oh hey, I added a new API to RubyGems. It let’s you ask for only
the data that you want. Here you go, it’s up, live in production, go. (laughing) So it was pretty great. If you’re interested in the details of that particular moment in history, Terence Lee and I gave a
talk at a Ruby on Ales, 2012, called bundle install Y U So Slow. And we talked about the
technical details of the API and the changes that we
had to make to Bundler to make that work. The very short version is if you had a fast connection, or I should say accurately, if you had a low latency connection to the RubyGem servers, the new API was amazing. You could ask for just the
information you knew you needed and then find out you needed
some more information, and then ask just for that, and then find out you needed
some more information, and ask just for that, download a lot less data overall, and as long as the latency was low enough that that multiple round trip
thing didn’t take too long, this was a lot faster. Unfortunately, it meant that you needed to make a lot more requests to RubyGems. And if you didn’t have
a low latency connection to RubyGems.org, like say you lived outside the US. There are a lot of devs
that live outside the US. Even if you just had a wireless
connection inside the US, it wasn’t any faster. If you were very lucky, it was basically a wash and
you just downloaded less data. But if you lived in South Africa, forget about it. I talked to some South African devs, and they talked about how
they would run bundle install after getting to work so that they could go make their coffee, drink their coffee, come back, wait a few seconds, watch bundle install finish, and then get to work. It was like a multi-minute process to just run bundle install once when your round-trip time to RubyGems is I don’t know, a second and a half. So the slowness was a huge problem and in response to these issues, we actually started working
on a new index format that would mean we didn’t need to make tons and tons of round trips to RubyGems. But it took like three
years to get done with that. So I’m gonna have to talk about that quite a bit later. Hang on, we’ll get there. At this time, we also continued to develop Bundler. We added stuff. We made it better for people. Some especially notable
things from this era include the clean command, which lets you get rid of gems that you aren’t actually using anymore. This was a super big deal for like CI or for Heroku, where you push many
versions of an application and you change the gems
that they’re using. And so before bundle clean existed, your CI setup and Heroku had to like choose between the
crappy options of either install all the gems again every time there’s a new version, which is very slow, or commit to letting your application have infinity space for gems because there was no
way to get rid of gems after you stopped using them. Bundle clean meant that
they could do both. And it was great. We added bundle outdated so that you could see what was out of date without having to actually update it. We added support to the cache command to let you cache Git repositories as well as just dot gems. And we added Git local development where you could check out a Git repository and make changes to the Git repository gem at the same time as you made
changes to your application and Bundler would watch the repo and automatically update
the commit in the lockfile to make sure that you
always got the right code. I’m gonna talk about that
in more detail later. We also added support for
application Ruby versions where you could put in your gem file the version of Ruby that your
application worked with and it would raise an exception
if you were trying to run it on a different version of Ruby, which especially when which
version of Ruby you were running was sometimes confusing. It was a really big help. You would never accidentally run your app on the wrong version of Ruby and then have really weird,
confusing bugs later. So… This feature wound up
causing some problems. But I’m also gonna have
to talk about that later. So for now, let’s move on to the next section of history where we find out all of the ways that we caused ourselves problems with the stuff that I just talked about. So, the biggest thing that
happened in 2012 to 2014 is Bundler adoption really,
really, really took off. Bundler 1.0 in 2010 averaged
like 8,000 downloads per day. Bundler 1.1 came out a couple years later and averaged like 20,000
downloads per day. And then by like August of 2012, it was averaging 30,000 downloads per day. And that’s when we discovered
that we had executed a distributed denial of service
attack against RubyGems.org. Yeah, basically the servers
just couldn’t handle how many Bundler users there were. And all those Bundler users were like I want to install gems. Tell me about the gems, RubyGems. And then RubyGems ran out of
server capacity and crashed and no one could install any gems at all. And everyone was very sad. So… To at least let you have
access to gems again, we had to turn off the
API that Bundler was using to make installs fast, and installs went back to being slow. And now we were back where
we were two years ago. So at this point, a team of people, including myself, Terence Lee, Larry Marburger, some other people, built a new standalone application that served just this API. And we actually got… The RubyGems team was super cooperative and with some help from Evan
Phoenix and David Radcliffe we actually got the old URLs to keep working with this new, completely separate application that we could scale
independently of RubyGems itself. As you may have guessed, while this did provide
an API for Bundler users, it provided a new completely
different set of problems that we had never had before. One of the problems was that we had a completely separate
database from RubyGems.org. And so, if you pushed a gem, we still had to find out
about that gem somehow before you could install it in a bundle. And we tried web hooks, we tried database replication, we tried scraping the API, we tried importing database dumps. There were problems with
all of these options, as I’m sure anyone who’s had
to deal with this kind of like distributed data
synchronization thing knows already automatically. We were young and naive and
had never had to do this before and we were like how hard could it be? (audience laughing)
It could be very hard. It could be very hard. So… Probably my favorite
problem that this caused was propagation delay
between pushing a gem and then being able to install it because you had to wait for
RubyGems to finish processing, and then send that information
over to the Bundler API, and then you had to wait
for it to finish processing, and then you would find out that even though you’d waited long
enough for that to happen, the CDN that we were using at the time would just kind of like
randomly not update depending on where you lived in the world. And so like, if you were Canadian, every fourth Wednesday, you couldn’t install
new gems for three hours and there was like nothing
that anyone could do about it. The other downside of the
standalone API is that we built it in Sinatra and SQL because it was super tiny and hyper-focused and just returned some
JSON and marshaled data. But… despite it being a completely
reasonable decision I think at the time, it meant that not as
many people were familiar with Sinatra and SQL in comparison to the RubyGems.org app, which was written in
Rails with Active Record. And so, we wound up with
a lot less contributors to the Bundler API. I think partly because people
didn’t know it existed. But also partly because even
if they did know it existed, they weren’t familiar with the like framework and tools that
we had built it on top of. There are entire talks about this process of DDoS-ing RubyGems.org, building a new API, and optimizing that API
until it was fast enough to actually support all of the
Bundler users in the world. I gave a talk called Deathmatch:
Bundler vs. RubyGems. And Terence gave a talk called bundle install Y U So
Slow: Server Edition, both in 2013. If that’s interesting to you, you can check that out
for a lot more details. On top of working on the API, we did still make some
cool new stuff in Bundler, including multithreaded installs, which was awesome. You no longer had to wait for the last gem to download and finish installing before you could start
installing the next gem. In those mythical 600 gem applications, this makes a really, really,
really big difference. We also switched to a
non-recursive resolver. Smit Shah kind of showed up in the issue
tracker one day and said, “I’ve never done this
open source thing before, “am I doing this right? “I completely rewrote Bundler’s resolver.” (laughing) And I said, wait, you did what? (laughing) And it actually worked. This was a really big deal because on JRuby in particular, the old resolver was recursive and would call itself again and again and use the arguments to the function to like retain the
state in each iteration. And unfortunately, on JRuby, every time you call a function, there’s not just a Ruby
stack with arguments, there’s also a Java stack with arguments. And Java stacks are big and basically maybe every… If you had a big application, or at random every fourth time, when you ran bundle install on JRuby, it would crash because
of running out of memory for all of the recursive call stacks. So that was not cool. This fixed that. And Smit Shah went on to become a core team member on Bundler after his first PR. (laughing)
So ridiculous. We also added https support. This was like around the same timeframe that GitHub was saying oh hey, you can actually connect
securely to GitHub and download things. So got that put into Bundler. And some uncool stuff, we
had Bundler’s first CVE security issue. The super short version is don’t put source in your gem file twice without making sure that
at least one of them is attached directly to a gem. If you have multiple sources, basically someone, because RubyGems.org is public, anyone can push a gem with any name. And so if you say kind of blindly, oh just pick gems from
any one of these servers, someone can put a gem that you don’t want on one of those servers. And you might get that instead. And that can be, doesn’t have to be, but it could be very, very, very bad. So to avoid that, you should use the block form of source where you say source
something do some gems after the first source, and then you’re fine. You’ll at least get the
gems from the source that you expect to get them from. It’s a little bit of a simplification, but you can read more
about it if this alarms you and you use multiple sources and you’ll figure it out. This is the point at which having a separate API totally sucked. And while the API was an optimization… So you could still install
gems if the API was down, which meant we didn’t like set it to wake us up at 3:00
in the morning if it went down. We figured… (clearing throat) Excuse me, we figured people
could install gems slowly until we woke up in the morning. But anytime it went down, we did get a lot of people complaining about bundle install suddenly
being very, very, very slow. And so it was exciting to like have this great practice
dev ops project really. Like, what’s the downside risk? You’re not gonna like break anything. But it slowly developed
into a huge source of stress because you’re like
thinking about making sure that it’s up all the time, every day. And no one wants to deal
with lots of stress, especially while not getting
paid and doing it for free, not very surprisingly. At this point, many of the people who had
previously been very enthusiastic about working on Bundler and RubyGems became very less enthusiastic. But, fortunately, as that was happening, the Ruby community kind of
simultaneously came up with several ways to start funding
development on these projects. Ruby Central, which organized this fine conference, has a fairly regular
practice of giving out grants to work on Ruby open source projects. Basically, if they have leftover money after running the conferences, they will pay devs to work on Ruby open source with that money. And that’s pretty cool. Grants to myself and other people on the Bundler and RubyGems teams meant that we were able to finish releases, keep working on the new contact index, bunch of other stuff. Around the same time, Stripe started their program where they give open source grants to let people work on open source for, I think the Stripe program
does three month grants. And one of the grants
went to a college student, who is named Sam Giddins, and he worked on CocoaPods at the time, the objective C equivalent of Bundler. And they didn’t have a
dependency resolver yet. And so his Stripe grant was
to build a dependency resolver for CocoaPods. CocoaPods happens to be written in Ruby. And so we kind of got
together and conspired and agreed to have this
dependency resolver get used by not just
CocoaPods but also Bundler, and also RubyGems. And today, it’s even used by Berkshelf, the Chef dependency manager. And we all share this like good, well-documented, actually relatively understandable dependency resolver library, which let me tell you
is a huge improvement over the previous Bundler resolver. This is also the point at which Stripe and Engine Yard started funding the
Bundler project directly. And on top of helping fund
some development work, that money made it possible for us to incorporate Ruby Together. And that’s how I have this shirt. And so, Ruby Together takes
funding from the community and uses it to pay developers to work
on community projects, which is pretty cool. Today, we pay for work, developer time, spent on Bundler, RubyGems, the RubyGems Rails app, the Gems-Gem server, ops work on the RubyGems.org servers, and we even started paying Christoph, the developer
of the Ruby Toolbox, to start working on the Ruby Toolbox 2.0 open source project, which is pretty cool. So, while Ruby Central
does give out grants and pays the bills for the servers, they don’t fund kind of
the ongoing maintenance that means that the servers
don’t go down in the future. As Ruby Together grows, we’d love to pay for more Ruby open source project development time. But we can only do that
if you and your companies sign up as members and
help fund that for us. So please check that out
and think about doing it. (thumping) Oh, I just knocked my coffee over, sweet. So, with support from
Ruby Central and Stripe and Ruby Together, the Bundler and RubyGems
projects started to see work done by paid devs on a pretty regular basis. We couldn’t afford to
hire anyone outright. But we could afford to
pay for a few hours a week from a few people. And probably not too surprisingly, paying people meant that they
showed up on a regular basis and actually got things done. And that was amazing. We were able to ship stuff
that had just kind of been sitting around, oh we
should do this someday for literally years. One of the big things we were able to do is finally move every
request to RubyGems.org behind the Fastly CDN, which was a huge improvement from before. Because before you would
make a request to RubyGems. RubyGems would say oh, this
is a gem that’s in Fastly. Go talk to Fastly. And then you would go talk to Fastly. And then Fastly would say
oh I don’t have a copy of this gem yet. Let me go talk to RubyGems. And then RubyGems would
send the gem to Fastly. Anyway, it was terrible. This is much faster. We were also able to move the Bundler API back into RubyGems.org. It’s no longer a standalone application. And thanks to having
people actively doing ops for RubyGems.org, we were able to… The new RubyGems can handle
the 10x increase in traffic that comes from having this API. And it’s not a big deal,
which is super cool. We finished the compact index, which is a way of telling Bundler users about gems without having to do that like infinitely recursive
round-tripping API thing. And it’s a big improvement. You can just keep a
copy of the list of gems on your computer, and you don’t have to
get it again every time. For a bunch more detail about that, check out my talk Extreme
Makover: RubyGems Edition from RubyConf 2013. Bundle install. Finally, sometimes, now fast. Couple other notable things
that we did in this period of actually having
people working on stuff. We made it so that you don’t
have to use the gem file, if you are not a fan of file files. We also made it so that
you don’t have to use the gem file dot lock if you are not a fan
of files named dot lock that can’t be deleted. There is a ticket on GitHub from I think eight years ago now, right after Bundler 1.0 came out that says dot lock is the
wrong extension for this file. And we were like, we believe you, it’s too late. (laughing) To be clear, this change is optional, even Bundler 2.0. We’re not getting rid
of either the gem file or forcing you to use gems.rb. It’s just an option that possibly makes life nicer for you. We also added Ruby version locking, because after adding the
Ruby version to the gem file, we discovered the problem was we didn’t know things like which patch release you were locked to. And we didn’t have the ability to let you change that version like between I don’t know point one, 2.2.1 to 2.2.2. Now you can and it’s better. We added a bundle lock command, which now lets you add platforms. So if you want to install
on an additional… Like if you want this
bundle to work both on say Unix machines and JRuby, you can now opt into that and install on both without a lock file that changes all the time. We added a doctor command from Misty Demeo that tries to help you figure out why your bundle isn’t working, especially if you have gems
that are in a weird state or the native extensions
haven’t been built or something like that. Pretty handy. We added a pristine
command, which lets you… It works just like gem pristine and lets you undo changes that you may have made
locally to your installed gems in your bundle. We added options for bundle update so that you say no, only
give me major, minor, or patch level changes, which was pretty handy. We added mirror configuration which lets you say oh, whenever I say gems from RubyGems, use this server that I keep locally that’s a mirror that
you can get to faster. And we added checksum validation. So now Bundler knows what the checksums of each gem should be and checks them. That’s what checksums are for. It’s pretty good. Can you tell that once we
started having funding, we started developing a little bit faster? There’s another slide. We shipped a plugin system in beta that lets you build command plugins like new bundle commands in
their own standalone gems. It lets you build life cycle plugins where you want to do something
specific after say… I feel like a great example
of this is you can generate ctags from gems in your
bundle as you install them, and source plugins. So in theory, tomorrow, if you want to, you could build a gem that
lets you install bundles from mercurial repositories. I don’t know of anyone
who wants to do that. But if you want to do that, could be you. So today, we’ve just shipped Bundler 1.16 with everything that I just talked about. We’re working on Bundler 2.0 with a target release date, very ideally, I’m crossing my fingers of Christmas. And I don’t have room in this talk to include details about 2.0, because we’re almost out of time. But Colby Swandale gave
a talk at a Ruby Kaigi, maybe two months ago, about just Bundler 2. So if that’s super interesting
to you, check it out. But the very short version is, while we do plan on making
breaking changes in Bundler 2, we think compatibility and stability are both super important. And we’re going to make
sure that it’s possible to have applications on your computer that some use Bundler 1,
and some use Bundler 2, and they will both keep working fine. We’re not gonna like force
everyone to mass upgrade to Bundler 2, because that would be terrible. I cannot even imagine dealing
with the support headache that that would cause. But, in the meantime, here are some cool things
that get you most of the way towards 2.0, but are just config options
that you can turn on today. If you turn on only
update to newer versions, then the bundle update command will never update you to an older version of a gem. Seems like a good feature. But we can’t turn it on
by default until 2.0. You can disable a multisource, and then Bundler will stop you from having an insecure gem file, and just raise an exception and say actually this is very bad and you’re opening yourself
up to security problems, also will be on by default in 2.0. You can turn on specific platform which tells Bundler oh, you should actually do your resolutions respecting the OS and CPU architecture and version that I am running on, which it didn’t do before. This will also be on by default in 2.0. And, you can turn on global gem cache, which is super cool, because it means that
Bundler only downloads dot gem files once and only compiles native extensions once, and then shares them across
all of the applications on your machine. Which pairs very well with another option, default install uses path, where every gem gets installed into its own place for the application, but that cache means that those gems don’t get downloaded twice, and Nokogiri, for example, doesn’t get compiled twice. It’s super great. (cheering and clapping) These options will also
be turned on by default in Bundler 2. Back to the https thing. Unfortunately we shipped
Bundler with a GitHub option that used http, which isn’t secure. But we can’t change it
because some people don’t have OpenSSL support in their Rubies. But you can change it. So bundle init creates a
gem file that does this. And you can overwrite
the GitHub option to say oh, only use https. We made it, that’s it. Now that we’re completely caught up on the history of Bundler, I have a few last second tips, and then we’re totally out of time. So here’s the chaser of workflows. Instead of bundle exec-ing, you can run bundle binstubs something. And that will create a new binstub, and bin whatever that you can
commit to your repository. And then anytime you run it, you will only get the
correct version of that gem for your application, instead of having to be
in the right directory, bundle exec, etc, etc. This is super handy for cron jobs, and honestly, like my muscle memory of
just running bin something is much easier than having a
shell alias for bundle exec. Bundle viz let’s you see your
dependencies in a graph. Wow, that’s really hard
to read, I’m sorry. You too, could have a
really hard to read graph of your application’s dependencies. (audience laughing) If you want to start
running your application on a new platform, like JRuby or Windows, you can use that lock option add platform and you’ll get a stable gem file dot lock that won’t change as you
install on both platforms. Pretty cool. The Git local development
thing that I mentioned earlier, you can check out a gem that
your application depends on, start using the local copy, make changes, Bundler will update the
lock file to the commit that you’ve made locally. And then when you deploy, Bundler will make sure that
you are still running the code that you expect to be running, rather than whatever you had
actually remembered to push. And, if you’ve ever wanted
to write a one file script that needs some gems, bundler inline is super good. Most people don’t know this
exists but it’s so good. You can write a script that
requires bundler inline, and then you just put a gem file block at the top of your script. And then you can start using the gem. It’s amazing. Here’s what it looks like when you run it. Even if you don’t have the gem installed, Bundler says oh I will
install that gem for you. Now your code can run. This is super great for
like single file scripts. Kind of came up earlier, you can search your gems using
the bundle show paths option which prints out all of the
paths that your gems are in. And then when you find the gem you want, you can open it directly
by running bundle open. And then you can edit it, finish your debugging, and then you can run bundle pristine to undo the changes that you
just made to that gem locally. It’s a pretty good workflow. And last and my personal favorite quality of life improvement, you can turn off post install messages, and no one will ever tell you to httparty hard again. (audience laughing and clapping) Somehow put that slide in twice. I’m sorry, there’s the punchline. The end. (laughing) (audience clapping) (metallic whooshing)

Leave a Reply

Your email address will not be published. Required fields are marked *