Rooftop Ruby Podcast

3: Creating Gems

February 21, 2023 Collin Donnell and Joel Drapper Episode 3
Rooftop Ruby Podcast
3: Creating Gems
Show Notes Transcript

How to create and publish gems.

Follow us on Mastodon:

Show art created by JD Davis.

Collin:

Hey Joel, how's it going? This week

Joel:

Hey, Collin. It's going. Yeah,

Collin:

we're back and you have internet and uh, and it's awesome.

Joel:

back. Yes. In fact, I now have two internet connections, which is

Collin:

Two internet connections. Oh yeah, cuz you got the backup one installed yesterday.

Joel:

Yes, I've got, um, I've got fiber, which is I think something like 500 megabits a second. They, they would give us a gigabit, but, um, I use it over wifi all the time at the moment, so there's just no point. And then I have like this backup vdsl connection, which is like 70, and I will eventually kind of try to merge them together with some kind of multi-line router I

Collin:

That's cool. That sounds very, uh, that sounds. Technical. I just have an arrow, so

Joel:

Yeah, I, I have similar, um, like deco systems, but I'm hoping to get it set up where if one of the connections goes down, it can just fail over.

Collin:

yeah, that'd be kind of amazing. That reminds me of the, um, that app you turn me onto Speedy, which is the, uh, the one where you tether, you can tether, but then it will, um, you're using wifi, but uh, it will just switch over to using the cellular connection if like one of them isn't working correctly or whatever.

Joel:

Right. You can tether over USBPre and connect to wifi at the same time, and it will do like channel bonding and in fact, there's few different. Like modes you can set it into. So you could set it to give you the best performance, in which case it will send like half the packets over one, uh, connection, half the others other over a different connection. Or you can set it to give you the most reliability and it will send the packets over both connections and then whichever one wins.

Collin:

No, I like that app a lot. I use it when I go to. Sometimes I'll work out of a cafe or a coffee shop, and uh, it's very useful for that because they're better than they used to be. I feel like a few years ago those were always very sketch and now they're tend to be okay. But it's nice to have it as like a backup and I don't have to like manage anything.

Joel:

I, I, I find that they like wifi in a coffee shop or on a train. When it works, it's usually okay, but then it, it sometimes just cuts out for like 10 seconds and that's enough to break your workflow. Whereas if you have this set up with tethering, then you just don't really notice because. Like either tethering or WiFi's gonna work at any given moment usually. Um, I actually use this on the, the Eurostar between London and um, well Paris, it was pretty flawless, like the whole way, had had internet basically the whole way, which is unbelievable.

Collin:

Yeah, I actually was thinking I want to use it when I take the Amtrak, which is like our crappy Eurostar. Um, when I take the Amtrak up to Seattle. From Portland the next time it's like three and a half hours from here to do that. So it's, it's kind of a nice ride. It's really beautiful. The West coast is just like all incredibly beautiful and you can see a lot of it that way. So it's a, it's a really nice ride. But, um, well, the thing I wanted to ask you about before I, I came prepared with a topic and that topic is, Have never, uh, published my own gems before or like really published a lot of open source and I've like contributed a little bit, but I'd really like to, I have a couple of ideas for things I'd like to make, and you on the other hand have published like a ton of different gems. I was looking at your GitHub and uh, there's, you have one, you know, you have Phlex and then you have like, you know, a couple different things related to Phlex you. Uh, an enum thing. You have a, uh, you know, e k states a bunch of different things and so I feel like this is a topic that you could guide me through and then I am going to become a, uh, you know, may, maybe not as on your level, but I can become a more prolific, open sourcer.

Joel:

I mean, I, I've published a ton of gems, but that doesn't mean anyone's using them. But that's where, that's where you.

Collin:

Yeah. I mean, would you say that you published a lot of gem. and then eventually, like Phlex is sort of caught on a little bit more, right?

Joel:

Yeah, that's, that's the one that caught on the most and the one that I felt I could take the furthest and would have the biggest impact. So that's the one I've been spending most of my time on. And a lot of the gems I've published now, um, are actually like extractions from Phlex. So, uh, Phlex was like this one big. And then I kind of extracted the testing parts and I extracted the, uh, the translations and Phlex Rails is now a separate gem, kind of trying to keep the core gem really small and simple. I didn't want the core gem to have too many dependencies. So it had, um, especially with like testing and stuff, it was beginning to get dependencies on Noka, gri and Cap. And obviously the Rails stuff had dependencies on rails. So extracting these smaller gem. It's, it's kind of nice cuz you can, you could still have in the main gem, like a command that lets you generate or like lets you install these other plugins. Maybe like adds them to the bundler or the gem. The gem file. I think it's, it's much nicer to like keeping everything separate.

Collin:

Well, the idea you were saying of you, you made a bunch of gems before Phlex that, uh, maybe got less caught on less. It just reminds me of anything where it's like you usually have to do something a lot of times, you know, before. It really, uh, catches on. Like if, you know, if you're making YouTube videos, usually somebody's first YouTube video doesn't get a million views, but like they have to kind of have a consistency to it and, uh, it kind of reminds me of that. So maybe we should start with very briefly, kind of a technical explanation. If somebody. interested in going from, you know, zero to having a gem somebody could put into their gem file. What, what does, what does that look like?

Joel:

It's surprisingly easy, actually, a assuming. We're talking about the point where you already have some pattern or like abstraction that you want to make into that gem. If you've already done the work of like separating the generic. Pattern out from your specific implementation of that pattern. And you've got like, I don't know, some, some files in lib. It's actually really easy to turn those into a gem. It's mu, it's much easier than you probably think. Like takes probably less than a couple of minutes. So a gem is basically, I prob, I'll probably get this wrong, but from my understanding, it's basically, uh, just a bunch of ruby files and a manifest that describes them, which is called your gem speck. And usually they're structured in a particular way. And that's, that's I think mainly because. Most people use bundler to generate their gem. Like it, it kind of scaffolds everything for you. So actually before, before you can use the bundler, I should probably take a step back. The hardest thing about building a gem, well, one of the hardest things about building a gem is of course, naming the Ruby Gems website doesn't have much space on it. It's pretty hard to find a name that is not being taken by some 0.0. Version that was released 15 years ago and hasn't been touched since then. So finding a name for your gem can be pretty challenging. And ideally you wanna find, like I was, I was like trying to name a gem just a couple of days ago and I was looking like tapping between hover to look up whether I could get a domain name, um, Ruby Gems to see if the gem name was. And then GitHub organizations to see if I could get a GitHub organization with the same name. And like sometimes you just can't, and you have to kind of fall back and do like dash ruby or something. But yeah, once, once you've got a name, it's, it's pretty easy. The, the other thing I would say, actually before we move on from naming, is it's definitely worth reaching out to people. If there's a name that you really want and you can see that it hasn't been used for age. But the author is still someone who has a profile on the internet and an email address somewhere. You might get lucky by just like sending them an email and being like, I wanna build a gem. I was hoping to use this name, but I saw it was taken. I don't think you're doing anything with this because you haven't touched it in 15 years, but like maybe you'd be willing to part with it. And, and you might get lucky and they might be able to transfer it to you, which would be pretty awesome. But yeah, assuming you've got a name, uh, the first step is actually to I, what I would usually do is run bundle gem, which is basically, uh, kinda like rails new for a gem. So bundle gem, you run it with the name of your gem and it creates a folder. Uh, a folder for your tests, A folder called lib, which is where your actual GEM code will live and a GEM spec. And if you open the gem spec, that is where you describe things like the name of the gem, the description, the source code url, any funding if you want, like open source funding. There's a funding mechanism through there. Now, I think, I think like a release notes or something like that, releases link, all that, all that metadata you can, you can put in that manifest, uh, called the gems.

Collin:

a part of this. I think also when you get to that stage,

Joel:

As well. Yeah, I'm, I can't quite remember. Um, so yeah, then, then you can copy your files into the lib directory and your tests into the test directory, or delete the test directory and create a specs directory. If, if you want, use our spec, set everything up, get it running. And then when you're ready to publish, all you do is you run Gem build, uh, and you give it the name of the gem. And it will tell you if there are any errors with your GEM spec, but otherwise it will create a GEM file for you, which is actually like a physical file with the Gem name. And then you can say Gem push, and then the name of the file that it built, and that's it. It will ask you to log in, and if you are pushing a gem with a name that's not taken, then it will register it for you and you're done.

Collin:

and then you're, somebody can add it to their gem file and use your thing. That's cool. So it's very easy. It's very.

Joel:

it's very, very easy. Yeah, you can, I, you can like build, like scaffold a gem and have it pushed up like just as, as quickly as you could. Write a quick description and paste in a URL in the gem spec.

Collin:

So that seems like a good technical sort of description of how to do that, which if you haven't done it before, it's actually like, uh, it's nice to hear it sort of all laid out. So. When you're coming up with something, you're like, I'm gonna, I wanna publish this thing. Does that usually start as like, I was,

Joel:

Mm-hmm.

Collin:

I basically already wrote the code form in one of my apps and now I'm going to extract it and then make a gem out of it? Or are you ever like, that would be a cool idea. I'm just going to make that.

Joel:

For me, it's a bit of both. Uh, there's a bunch of stuff that I built in an app and then decided this is something that is worth extracting and building up on. And then did that extract extraction? Usually it would be something that I'd already made quite generic in the app, but a lot of the time I'll just have an idea like play date was one of those ideas where. I had nothing to start with. I just knew that I wanted to have, I kind of knew roughly what interface I wanted. this is a gem. It's very, very much work in progress where the idea is that I want to be able to build calendar views very quickly, so I want to be able to enumerate date objects. So I wanna be able to say, for example, given this month, give me each of the days, and then for each of the days, maybe give me each of the hours. Or something like that. Right. And maybe like highlight if it's a weekend day. Uh, so, so the day objects should have predicates. So I wanted to build like a date library that, that had custom enumerators and ranges. And so that was like my idea. I had no code written for it, but then I just kind of said bundle gem, playdate. And then started from there. Whereas like other stuff like think action state, uh, which is a library to help. Kind of build predicates and scopes in the same code. Um, so like rail scopes and predicates can be built using the same thing. That's one that I kind of originally did in an app. Uh, and then was like, this is kind of cool. I should just extract this. Uh, that was actually the first gem that I published. And I think what made a huge difference to me was, I think a few days after I published that. Casper opened a PR on it, like tweaking something. Casper Tim Hansen. And I was just like, what? This is like insane. I've never posted Jen before. I've never done open source before. And someone's actually just opened a PR and they obviously like the idea and they want to contribute to it, and I thought it's really cool. And since then I've just been hooked on open

Collin:

Must have been very encouraging. So that'll make sense. And then, all right, so let's say play date, right? You, you decided you wanted this object-oriented dates, Ruby Dates library, uh, to be able to do all these things that you said. How long are you working on that before you're like, go, before you make it available for anybody else?

Joel:

I try to make it available straight away because I want the name. I don't want to, I don't want to like think that I've got a name and start working on something and then have to rename it so, I pretty much will say, and I dunno, this might even be against the terms, but I'll say Bundle Gem, the name, and then I'll like, just go into the Gem Spec, type out some very quick, like coming soon details and push it to, to Ruby Gem straightaway as like,

Collin:

Just to park the name space,

Joel:

yeah, just to park the baby space. And then after that I'll start like working.

Collin:

you just basically do it immediately, even if it's like marginally functional, maybe at this point.

Joel:

Yeah, it might not even have anything. I just won that name and I've like, maybe I've bought the domain name and I just really want to have the, the Ruby Gem's name. Otherwise, I, I may as well not have bought the domain name. Yeah. I, I just can't, I can't imagine starting to work on a library. Thinking's gonna be called something and then you go register it and someone's taking it.

Collin:

I think that's a good way to go. And the reason is that for me, I feel like I have a little bit of stage fright, or I'm a little bit scared to put something just out there for people to see if I haven't done that a lot before and you know they're gonna see my code. which actually is a good thing though, like employers and stuff. That's helpful. Uh, but still, um, there's a little bit of stage right there. And then also things for me, if I haven't quite figured out like what is the API for this actually gonna look like or whatever. I feel like I'm hesitant to sort of hash that out in public in a sort of way. But maybe that's, maybe that's silly. Maybe that's, uh, maybe that's why I haven't published a bunch of gems. And you have.

Joel:

It's, I don't know if I'd call it silly. It's totally understandable, and I, I completely get it. I, I think what helps. Is just getting it published early. Actually, the earlier the better because then there's less pressure. If you publish it and you're like, I've been working on this for five years, then the expectation or the expectation that you think people will have is that like, this should be five years worth of work. But if you just publish something that is like completely empty, it's a blank slate and you're just starting from scratch. It's not like that big step every, like every time you make a change, you're publishing that very small change, assuming you're building an open source gym. Right? And I think that's just a lot easier. Like you don't have that, that big like release hurdle where like suddenly I'm gonna make all this private source code public instead. It just happens really

Collin:

That makes sense and I think that is a good policy that I'm going to try and adopt something that would concern me a little bit, and I bet you've probably experienced this, is if you aren't quite sure what the sort of interface for this should be, are you ever worried that you're like kind of hashing that out and or is it that, uh, That becomes more of a concern once people are actually using it. Right. I feel like something like Phlex, probably a little bit higher stakes to like drastically change how the interface works because people will have to then update their code to do that.

Joel:

Right. I think that is why, like that's what, that's what beta releases are for is like this might completely change and it's important to not. Publish a 1.0 release too soon, I think, and just take a lot of time with the beater and make sure that the API feels right and it's okay to, like, you can have a bunch of people using your beater, but everyone who's using a beater knows it's a beater. They know it's pre-release. They're happy to dig into the code if there's a bug, and they're likely to come and give you suggestions on how to. That's, that's been my experience. And like Phlex changed the API a lot. Like some stuff stayed pretty, pretty much the same. But Phlex, I mean just things like, originally Phlex used to be called Phlex. Um, so Phlex h Phlex HTML as it's called now, used to be called Phlex Component. And then I renamed it Phlex View, and then I renamed it again because I realized that I didn't just want to do html. I wanted to do SVG views and possibly Jason views and maybe some XML views. So yeah, renamed. Renamed from from Phlex View to Phlex HTML yet again, which I felt like really guilty about, but it was pre 1.0 and it's, it's definitely. Like, definitely get things right before you do that because the pressure of like making an API change after 1.0 or like at least too soon after 1.0 is quite high that I've been exploring whether or not, and I always go back and forth on this and it's a, it's a very tricky and difficult question whether or not Phlex Hml should have. a module instead of a super class, like an abstract super class. And that is really tough and I don't know what the right answer is, but I went with abstract class and I don't feel that I can change that now, at least not for a while. If I do, it's really a 2.0 release and I'm just not ready to do a 2.0 release. I don't have enough. I don't know, I, I think I want to explore further what 1.0 looks. And like have more things to bring with 2.0 other than just, yeah, instead of a class, it's now a module. And yeah, enjoy changing all your

Collin:

That absolutely makes sense, and I feel like as a developer, I'm kind of used to the idea of when something changes their major. Number that implies to me there might be some breaking changes.

Joel:

E I mean, even a minor version number can have breaking changes, but they're usually not. Like huge breaking changes. A rename isn't, isn't necessarily a big deal, but like changing completely, changing the design of something, completely changing a pattern. I would try to do that in a 2.0.

Collin:

That totally makes sense to me. So I think the takeaway there that's really for me to think about and maybe other people, is just that there's not really any pressure. You can make something and be like, this is a beta, it's, you know, I haven't really, I'm still figuring it out. And if people want to contribute they can. And just let people know that, like you can just say that. And it sounds like in general, folks are pretty understand. They know what that.

Joel:

And, and like the folks that do use it and, and some people will, like Phlex Rails is still in beta and people are using it in production, but those people. Know that it's beta and they have made the decision, this is valuable enough to me that if something goes wrong, I might have to go and fix it myself. And maybe they've, maybe they've read the source code so that they can do that. And those people are great. Like you want your beta to be battle tested in production, ideally, because that's where you're gonna find all of the edge cases that you wouldn't necessarily come up with. Like Phlex Rails being tested in production with hundreds of components is absolutely brilliant. There's so many things that have been found or like, I don't know, just like realizing this idea that I had kind of just doesn't actually work, like for real. Um, and maybe, maybe we need to reconsider it. Yeah. So I don't know. I've definitely, I, I would definitely recommend. Just get a beater out. Like the thing about beater as well is you don't necessarily need to have full test coverage or like you're not, and you're doing open source, you, you're not having to provide people with support. There's no real pressure there. It's just like a hobby project that you can share with others. And what's great about that is. Like someone might come along and open an issue or open a pull request and change something or suggest something. And usually that is a really positive experience in my experience, at least probably because like none of my stuff is popular enough that I've got any of the like trolls or I've, I've not had any negative open source experiences yet, but I, I know that, that that is a thing.

Collin:

I mean, and Ruby people tend to be, you know, salt of the earth, the kindest people in the world. So yeah, Matt's is nice. So we're nice. I think that's all really good. Um, and the lesson I'm taking away is just publish early, publish often get a good domain,

Joel:

Yeah.

Collin:

and there's really no downside to that. And actually it's all upside because you're going to be able to get more input earlier, so you're not like pre-commit yourself because you've been working on this for a long time and now you have all this infrastructure in your thing around it. If somebody else sees it very early, it's very easy a change thing, and that's probably going to be a good thing. So I think that's all. Helpful, and I'm going to take that to heart by, by the time we publish another episode after this one, I'm going to have made a gem and it will be there and I know what it's going to be. So I'm I'm not starting from zero. I already know what it's going to be and I already know it'll make a good gem, uh, which is, um, I've been playing around a little bit. The play date, not your play date. The little handheld console play date by the folks here at panic. And in their SDK they have something called an animator, which is basically, you can give it like a animation curve, like ease in ease, in ease out, that kind of thing. And then I was also playing with Ruby 2d, which is a Ruby Game framework, and they don't have that. Uh, and I. If there was a way for me to basically create an animator and say, I want this kind of curve, and then get fed the numbers so that I can do something with them in Ruby 2d, that would be very helpful. And so I'm going to make that gem and then we can talk about that and that'll be good. Well, I think we can call it there. So I'm gonna make a gem. Everybody else should go look at all of, uh, Joel's stuff that he talked about and, uh, yeah, I think this is, uh, I think this is really good.

Joel:

I I, I would add one more tip, which is, and you don't need to do this very early. You can, and it's, it's probably good practice to do this early as you're doing beta releases. But every time you do a release, go into GitHub and add a release there. Uh, create a tag with the, the release number because it's just so good being able to like have tagged version history based on when you did a release and to be able to go back and like look at what changed in the code between versions. Like if you have a bug. Happened, you know, like where that bug, what, which release releases that bug affected, if that makes sense. So that's, that's very useful. Um, and my process is usually I change the version I commit and push it up and make sure the test pass. Then I go and make a tag and then I build it locally and push it up to Ruby Gems and then I publish the tag. So something like that, uh, there's probably ways you can kind of automate that better. I just, I just do it manually.

Collin:

That sounds like a really good tip. That's a good workflow to have in mind. Yeah. So that's great. And uh, Thanks for teaching me how to make a gem, Joel.

Joel:

You're welcome.

Podcasts we love