GoRuCo 2018

Locking It Down with Ruby & Lockfiles

GORUCO 2018: Locking It Down with Ruby & Lockfiles by Danielle Adams

GoRuCo 2018

00:00:14.330 Hey guys, as Luke said, I'm Danielle. I was here two years ago for my first career Go talk, or actually my first talk ever. I was pretty sure I was about to have a heart attack, but luckily I didn't, and I'm here today. Thanks to all for coming. In all seriousness, I'm going to talk about dependency management in Ruby. I'll share some things I appreciate about it and discuss how I think we can evolve.
00:00:35.210 So let's get started. There are two things you should know about me. First, I have a cat named Dennis. I had some paranoid thoughts that maybe he was trying to kill me, and when I took a quiz online, I found out I was right! So, this is him. The second thing is that I work at a company called Heroku, focusing on developer experience. I've been there a little over a month, and I have only broken one thing, so things are going pretty well!
00:01:04.619 Now, let's talk about dependency management in Ruby. Initially, when I proposed this talk, I was a little ambitious with the title. I had to shorten it for a ten-minute talk, so it became 'Locking It Down with Ruby.' Or as I like to say, it’s about the things I appreciate regarding Ruby package management and dependency locking. I started thinking about this because, as you heard before, I write a lot in Ember and JavaScript. There’s an ongoing conversation about the two conflicting ways to lock dependencies in a JavaScript application: NPM and Yarn — and of course Bower, who’s just watching from the sidelines.
00:01:40.440 There's a lot of discussion about how to lock dependencies, and it can be confusing. Even if you're experienced with the project, navigating these different methods can be a challenge. Since I started working on JavaScript applications, I've encountered various practices. When I talk about locking, I'm referring to locking an entire dependency tree for an application or locking a dependency that exists within the application level.
00:02:09.690 I’ve been managing JavaScript for a couple of years, which is quite a bit. The first method I've tried, which works okay, is pessimistic locking. This involves modifying the version of your package.json file — which is the equivalent of Gemfile — by stripping out the syntax so it gives a specific version rather than a range. When you install your packages, it resolves to that specific version. I've used this method, but there's also a shrinkwrap method that I won't get into, and it wasn't very effective.
00:03:02.160 Then, about a year and a half ago, Yarn came out, and six months later, NPM introduced their own lock file. This has sparked an ongoing discussion about which method is better. Now, I want to go back and provide a brief history of how Ruby came to be and how its dependency ecosystem evolved.
00:03:34.890 Originally, Ruby was released in 1995; I'll call that year zero. RubyGems was introduced in 2004, about nine years after Ruby. I'm combining RubyGems.org and the RubyGems tool because it simplifies the discussion, but they are separate components. Five years later, in 2009, Bundler emerged as a solution for managing dependencies, particularly after Rails was released. Different applications needed a more robust version-locking system.
00:04:24.225 Now, let’s talk about the good parts of Ruby dependency management. First, in my opinion, installing gems and managing them at the application level is really straightforward. You can see that you can easily install the command-line tool, which is just Rails. That initiates a Rails application with or without running Bundler. From there, you can add a gem library to your application, and you have the ability to run the specific version you need.
00:05:01.980 This is beneficial when you have different applications running on the same operating system, as Bundler scopes to the correct version, so you don’t have to worry about compatibility issues. One of the highlights is how Bundler resolves dependency conflicts, which often goes unappreciated. It’s an impressive mechanism that helps alleviate a lot of developer headaches.
00:05:51.810 Bundler utilizes your Gemfile to determine dependencies, as shown in an example I have. I learned while preparing this talk that I18n stands for internationalization. It consists of 18 letters between I and N! In this scenario, you might specify a dependency on a gem called concurrent Ruby, wanting a particular version in your application. Bundler will analyze this and generate a corresponding Gemfile.lock file, ensuring that it resolves correctly at the application level.
00:06:29.490 So even if you haven’t specified a dependency version, Bundler will determine an appropriate version through its backward resolution process. It analyzes dependencies and helps ensure you have a working application. This is one of the things I appreciate about the Ruby ecosystem.
00:07:07.860 Packaging and developing Ruby libraries is also remarkably simple. All you need is to create a folder containing your files, and RubyGems provides the necessary tools to create a packaged file. You can then push it to RubyGems, where it's stored and made readily available to developers for use in their applications or command-line tools.
00:08:00.699 Lastly, it's great that both Bundler and RubyGems are written in Ruby. This makes debugging much easier for developers, as you can step through your tools without needing to learn a new language. For instance, the command to install a gem is straightforward and reveals how it operates under the hood, which is particularly beneficial when troubleshooting.
00:08:53.060 In conclusion, I believe the tools provided by Ruby for dependency management work exceptionally well. While there are other languages and communities that Ruby can learn from, the Ruby ecosystem is quite robust. There are always areas for improvement, but overall, I'm quite pleased with how Ruby manages dependencies.
00:09:46.980 Thank you!