00:00:11.990
Before we get too far, I just want to take the opportunity to set some expectations. If you've been to one of my talks before, you know they tend to be quite interactive. However, this talk will not be as interactive. I had sent out a tweet making this clear, as I wanted to give you a primer on what to expect. This talk will essentially be a walkthrough on how to extract small libraries, encapsulate them into RubyGems, and publish them. If you feel that this topic is still suitable for you, and you want to learn about gem publishing, then this will be perfect for you. But if you've done a lot of gem publishing before, this may be a bit too cursory for you. I completely understand if you decide that this isn't what you want; I'm not offended at all.
00:01:14.100
My name is Adam Cuppy, and I am a principal at a web and mobile consultancy called Zeal, based in Oregon. We specialize in many of the topics I’ll be discussing today. If any companies are interested in training or development of some kind, we would love to work with you. If not, that’s totally fine too! You can find my Twitter profile here, and I welcome interactions there. I love working with people and helping to fill in educational gaps. Another thing I want to ask is that since we are quite spread out, please come forward. There’s plenty of space here, and I would appreciate if you all could fill in the front. Don't be shy; we are all friends here!
00:02:18.600
Everything you see today will be published online, so feel free not to take copious notes. It’s actually easier for presenters to see your faces rather than just Apple logos. Just keep in mind that everything is going to be available online, including this talk, which is recorded. If you have any questions during the talk, just keep a mental note of them. I am more than happy to answer your questions. I’m on GitHub as a Cuppy. All the code you’re about to see has been published either under my name or under coding zeal. My Twitter profile is there as well; feel free to tweet at me!
00:03:10.500
This presentation is affectionately titled 'Pluck It,' focused on extracting micro-libraries and building RubyGems. This track revolves around the theme of less code and is based on our experiences at the consultancy, which I've been part of as a Ruby engineer. We realized that there are many fantastic opportunities to create gems that are less than a hundred lines of code; they don’t need to be large at all, and doing so can be quite beneficial for various reasons, which I will discuss later.
00:03:32.699
To start, we will look at a basic Rails app. I know we’re at a Ruby conference, so please forgive me. You can throw food at me later. The fact remains, even though I’m utilizing a Rails app for this example; you could also use a Sinatra app or Lotus, which is a cool framework. In fact, it could work with any Ruby library that can leverage RubyGems. For this talk, I’m using a Rails app to illustrate the point.
00:04:01.259
Most Rails apps will have a models directory where we find the source material for extracting micro-libraries. Micro-libraries often center around services; they might be some sort of factory or builder code. Another place to look is in your controllers, especially inside the controller code where you handle interactions. There’s a good chance you’ll find a lot of duplicated code there too, providing a big opportunity to extract micro-libraries from that.
00:04:43.380
For instance, if we look at a basic User model, we see some functionality baked into it. There is an attribute on the user model that pulls in a Gravatar URL. To do this, we have a constant that specifies a URL template based on the Gravatar documentation. We also have a public method called gravatar_url that builds the URL and returns it. There’s a private method on the user object that creates a hash hex value for the user’s email address. This implementation is quite basic, but it highlights a larger issue. How many of you are familiar with the Single Responsibility Principle?
00:05:55.349
This is where we run into problems. Essentially, we are placing functionality into an object that doesn’t care about how the URL is built; it just needs to know that it exists. Therefore, it’s common to extract this code and put it into its own class. We could create a new class in the lib directory called Gravatar and move the functionality from the user object into this new class. This is a simple process and allows for additional features, such as supporting different sizes of Gravatar images.
00:06:41.190
Going back to our User model, we can now start reusing the code by calling the Gravatar library we created. This is a good and straightforward fix and is frequently done in Rails applications. When you have code or functionality that is application-agnostic or domain-agnostic, it’s a good idea to extract it so that you can manage it more effectively and create a better testing environment, free from interference with the user model.
00:07:33.240
This leads us to a vital question: How many times have you written the same small bits of code over and over, thinking, "If only this were significant enough to be a gem!"? We often find ourselves creating single-file gems. You know what I'm talking about; one file we can reference back to in different applications. Or we might just pass it around, sharing the code without telling anyone. Such practices are not sustainable, especially when it comes time for updates. For example, if you’ve written code now in production, and you lose access to that codebase, what do you do if you find a bug?
00:08:32.760
This frequent occurrence makes it essential to consider RubyGems. Most of us familiar with Ruby know that every project that uses external libraries employs RubyGems to manage those dependencies. To put it simply, a Ruby gem is a packaged collection of files, or one or more files bundled together, that can be utilized across projects.
00:09:44.010
It’s important to note that while RubyGems helps manage packages, Bundler is the tool we use to manage dependencies. Each Ruby gem has a version, and Bundler helps you handle all the intricacies of dependencies to ensure your application runs smoothly with the necessary library versions. Prior to Bundler’s widespread use, handling dependencies was an absolute nightmare. Now it simplifies things immensely.
00:10:39.180
When we run our application's Bundler command, we can see a simple output that shows which gems are being used. Bundler retrieves these gems from RubyGems.org or potentially a private gem server, if applicable. This way, we can manage our application's dependencies very effectively.
00:11:49.310
Now, it's essential to understand that while we often think of RubyGems and Bundler as interlinked, they serve different purposes. RubyGems is the package manager while Bundler focuses on managing dependencies. It is not uncommon to see variations in the version of a gem and even a lack of awareness of how things work beneath the surface.
00:12:46.760
As a quick overview, generating a gem with Bundler is straightforward. You run the command `bundle gem` followed by the name of your gem. This generates several crucial files: a `lib` directory, the main gem file, a version file, README and LICENSE files, and some useful configuration files for the build process. These files will serve as the foundation for your gem.
00:13:41.050
The generated code is quite handy; the `lib` directory includes a file to require the version and sets up a module for our gem. This is an important practice to avoid conflicts with any other gems and to maintain proper organization. Within that `lib` directory, we can create our specific classes and functionality.
00:14:38.000
After structuring our gem, the next step is to make sure we correctly implement any necessary tests. There's a generated `spec` directory as part of the bundling process, where you will create your tests to verify that everything functions as expected. Once this is done, you would run the test command to ensure that everything passes.
00:15:42.960
After your tests are in place and passing, you need to modify the `gem_spec` file to set the gem's properties. This includes the name, version, author details, and descriptions which will help others understand what your gem does. By encapsulating all essential information within the gem itself, you reduce chances of information becoming out of sync with external sources.
00:16:56.300
Finally, once you're satisfied that your gem is working, you build the gem by running `gem build` followed by your gem's specification file. This generates a `.gem` file that you can push to RubyGems, making it available for use. Once published, it becomes a resource that others can access and utilize.
00:18:08.050
There are many advantages and disadvantages to creating RubyGems. Some benefits include managing dependencies more effectively and the ability to isolate your code from your application. This last point is especially useful as it allows you to handle updates and changes independently. However, it introduces additional overhead and requires ongoing maintenance. It can complicate the process of making changes because you’ll no longer be able to directly modify the code.
00:19:12.599
In summary, extracting functionality into gems is most beneficial when the cost of maintaining internal libraries exceeds the cost of maintaining external dependencies. If your code is widely reused across different applications, it can often make sense to pull it out into a gem. This can vastly improve your team’s development workflow and the maintainability of your projects.
00:20:21.579
To illustrate this concept, consider small gems like Truman, which is a simple truth value manager created with only 30 lines of code. It's a small utility but its value is evident. Another example is Gravis, a small library that was extracted for generating Gravatar hashes, which showcases how even tiny libraries can be successfully published as gems.
00:21:19.130
As we approach the end of this talk, remember that there are vast resources available to help you with RubyGems, including a detailed guide on rubygems.org. If you have further questions, don’t hesitate to reach out through Twitter or GitHub. I truly value community engagement and would love to assist anyone interested in further exploring RubyGems.
00:22:14.910
Thank you all for attending! Are there any questions before we wrap up? Yes, I recommend various services for private gems. There are some that offer authentication, which is essential. If you need an ad-hoc solution for private gems, you might consider mounting the gem from a local directory incorporated into your application. But it is often better to use a dedicated gem server that allows for authentication. Thank you once again for being here, and I hope you have a great rest of the conference!