<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fion L</title>
    <description>The latest articles on DEV Community by Fion L (@fionl).</description>
    <link>https://dev.to/fionl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F576521%2F623a875b-0468-4231-85ee-ae441f694330.jpeg</url>
      <title>DEV Community: Fion L</title>
      <link>https://dev.to/fionl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fionl"/>
    <language>en</language>
    <item>
      <title>How to Make a Ruby Gem – A Developer's DevOps Perspective</title>
      <dc:creator>Fion L</dc:creator>
      <pubDate>Tue, 08 Jul 2025 16:11:44 +0000</pubDate>
      <link>https://dev.to/fionl/how-to-make-a-ruby-gem-a-developers-devops-perspective-1c0i</link>
      <guid>https://dev.to/fionl/how-to-make-a-ruby-gem-a-developers-devops-perspective-1c0i</guid>
      <description>&lt;h2&gt;
  
  
  Learn how to create and publish your own Ruby gem, from skeleton generation to deploying on RubyGems.org, with a focus on the DevOps approach.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;As a software developer, it's easy to find ourselves constantly building apps—web apps, mobile apps, admin dashboards—but creating a Ruby gem is a whole different game.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s not just an exercise in programming, but also a challenge in packaging, documentation, testing, and deployment. In this post, I’ll walk you through how I started developing a Ruby gem, with a special focus on the DevOps pipeline and publishing to &lt;a href="https://rubygems.org" rel="noopener noreferrer"&gt;RubyGems.org&lt;/a&gt;. This guide will grow with time, as the gem matures, so feel free to comment and contribute!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build a Ruby Gem?
&lt;/h2&gt;

&lt;p&gt;This project is both personal and professional. It’s a chance to step beyond app development into the world of software tooling and libraries—creating code that can be reused and extended by other developers in the Ruby community.&lt;/p&gt;

&lt;p&gt;Building a gem is also a fantastic way to understand how Ruby projects are structured, versioned, tested, and published, which is a core skill for any serious backend or full-stack developer.&lt;/p&gt;

&lt;p&gt;Whether you want to open-source your gem, use it across multiple projects, or simply understand how bundler, versioning, and packaging work in Ruby, this is a great learning journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Prepare Your Development Environment
&lt;/h2&gt;

&lt;p&gt;Before diving in, you need to have Ruby and Bundler installed on your system.&lt;/p&gt;

&lt;p&gt;Install bundler (if not already installed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs the Bundler CLI globally, so you can now use it to generate new gems and manage dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generate the Gem Skeleton
&lt;/h2&gt;

&lt;p&gt;You can now generate your gem’s scaffold using Bundler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle gem your_gem_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command sets up a project structure including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;lib/&lt;/code&gt; folder where your main code goes
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;.gemspec&lt;/code&gt; file which describes your gem
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Gemfile&lt;/code&gt; to manage development dependencies
&lt;/li&gt;
&lt;li&gt;A README.md, a Rakefile, and test setup (RSpec or Minitest)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it organized—your main file should live in &lt;code&gt;lib/your_gem_name.rb&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create a GitHub Repository
&lt;/h2&gt;

&lt;p&gt;Now it’s time to version control your project. Start by creating a new GitHub repository and then connect your local gem folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git remote add origin https://github.com/your_username/your_gem_name_gem.git
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial commit"&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives your gem a public home and enables collaboration, issue tracking, and documentation hosting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Set Up Your RubyGems.org Account
&lt;/h2&gt;

&lt;p&gt;To publish your gem, you’ll need an account on &lt;a href="https://rubygems.org/sign_up" rel="noopener noreferrer"&gt;RubyGems.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After signing up, RubyGems will provide a command like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-u&lt;/span&gt; your_username https://rubygems.org/api/v1/api_key.yaml &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.gem/credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run this in your terminal. It will save your RubyGems credentials securely.&lt;/p&gt;

&lt;p&gt;Set proper permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;0600 ~/.gem/credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Understand the &lt;code&gt;.gemspec&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;Your gem’s &lt;code&gt;.gemspec&lt;/code&gt; file is its identity card. It defines metadata such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;authors&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;summary&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;files&lt;/code&gt; to include&lt;/li&gt;
&lt;li&gt;Any required dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simplified snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your_gem_name"&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;version&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;YourGemName&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;VERSION&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A simple tool to do XYZ"&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"This gem helps developers do XYZ in a clean and efficient way."&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authors&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Your Name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"lib/**/*.rb"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure &lt;code&gt;spec.files&lt;/code&gt; includes all the files needed for your gem to work properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Build the Gem Locally
&lt;/h2&gt;

&lt;p&gt;Once your code is ready and the &lt;code&gt;.gemspec&lt;/code&gt; file is filled out, build the gem locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem build your_gem_name.gemspec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;.gem&lt;/code&gt; file, which is a packaged version of your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Push the Gem to RubyGems.org
&lt;/h2&gt;

&lt;p&gt;Time to publish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem push your_gem_name-x.y.z.gem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once pushed, your gem will be available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://rubygems.org/gems/your_gem_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anyone can now install it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;your_gem_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or include it in their Gemfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'your_gem_name'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8: Gemfile vs. Gemfile.lock
&lt;/h2&gt;

&lt;p&gt;Let’s clarify these two files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemfile&lt;/strong&gt; — declares your project’s gem dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemfile.lock&lt;/strong&gt; — freezes those dependencies to specific versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates or updates the &lt;code&gt;Gemfile.lock&lt;/code&gt;. You can think of it like a &lt;strong&gt;balance sheet&lt;/strong&gt; snapshot of your gem’s dependencies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Do not edit &lt;code&gt;Gemfile.lock&lt;/code&gt; manually. Use &lt;code&gt;bundle update&lt;/code&gt; to manage locked versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bonus: Development Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Write tests (RSpec or Minitest) from the beginning
&lt;/li&gt;
&lt;li&gt;✅ Use &lt;a href="https://semver.org" rel="noopener noreferrer"&gt;semantic versioning&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✅ Keep your README and inline documentation updated
&lt;/li&gt;
&lt;li&gt;✅ Use &lt;code&gt;rake release&lt;/code&gt; to automate tagging and gem publishing
&lt;/li&gt;
&lt;li&gt;✅ Treat your gem like a product: maintain it well&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; What’s Next
&lt;/h2&gt;

&lt;p&gt;This guide focused on the &lt;strong&gt;DevOps essentials&lt;/strong&gt; for building and deploying a Ruby gem. You’ve learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up a gem project&lt;/li&gt;
&lt;li&gt;Publish it to RubyGems&lt;/li&gt;
&lt;li&gt;Understand its structure and versioning&lt;/li&gt;
&lt;li&gt;Use Git and GitHub for open-source development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;strong&gt;next blog post&lt;/strong&gt;, I’ll cover the &lt;strong&gt;actual purpose of the gem&lt;/strong&gt;, how I’m implementing its functionality, and how I plan to test and maintain it long-term.&lt;/p&gt;

&lt;p&gt;Want to contribute or share your gem journey? Leave a comment or open a GitHub issue. Let’s build better Ruby tools—together. 🚀&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>gem</category>
      <category>devops</category>
      <category>bundler</category>
    </item>
    <item>
      <title>Lost your README?</title>
      <dc:creator>Fion L</dc:creator>
      <pubDate>Tue, 04 Jun 2024 17:10:44 +0000</pubDate>
      <link>https://dev.to/fionl/lost-your-readme--129f</link>
      <guid>https://dev.to/fionl/lost-your-readme--129f</guid>
      <description>&lt;h1&gt;
  
  
  When &lt;code&gt;git push&lt;/code&gt; Breaks Your Flow: A Cautionary Tale of Lost Mojo (And How to Get It Back)
&lt;/h1&gt;

&lt;p&gt;We've all been there. You're coding away, everything’s flowing smoothly, and you've just squashed a bug or added a feature that makes you feel invincible. You’ve done your &lt;code&gt;git add .&lt;/code&gt;, dropped a poetic commit message, and now you're ready to share your work with the world. The final move: &lt;code&gt;git push -u origin master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But wait.&lt;br&gt;&lt;br&gt;
Red text.&lt;br&gt;&lt;br&gt;
Push rejected.  &lt;/p&gt;

&lt;p&gt;Suddenly, your momentum is gone.&lt;/p&gt;

&lt;p&gt;For a second, you're staring at your terminal wondering if Git just betrayed you. You retrace your steps. Was it a rebased commit? A remote mismatch? Something about history diverging?&lt;/p&gt;

&lt;p&gt;This isn’t the first time this has happened to me — and it probably won’t be the last. But each time, it chips away at that coding mojo we work so hard to maintain. It's a moment of panic, a slice of self-doubt, and a brief identity crisis all rolled into one.&lt;/p&gt;
&lt;h2&gt;
  
  
  My Mistake
&lt;/h2&gt;

&lt;p&gt;In my case, I wanted to get my latest changes up to GitHub. Simple enough. So I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And boom — rejection. Some upstream mismatch. I felt deflated.&lt;/p&gt;

&lt;p&gt;So what did I do?&lt;/p&gt;

&lt;p&gt;I panicked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-f&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, I &lt;em&gt;forced&lt;/em&gt; the push. Yes, I knew the risks. But sometimes in the heat of the moment, logic takes a back seat and your fingers go rogue.&lt;/p&gt;

&lt;p&gt;Did it work?&lt;/p&gt;

&lt;p&gt;Technically, yes. The push went through. But when I opened GitHub, it was like I’d stepped through a time warp. README files and changes from previous commits had vanished — overwritten like an embarrassing childhood diary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Redemption in Stack Overflow
&lt;/h2&gt;

&lt;p&gt;After a few deep sighs (and possibly a snack to comfort my inner developer), I hit the forums. I landed on &lt;a href="https://stackoverflow.com/a/59790434/11083275" rel="noopener noreferrer"&gt;this golden post&lt;/a&gt; which outlines the safer, cleaner steps to take when your &lt;code&gt;push&lt;/code&gt; is rejected.&lt;/p&gt;

&lt;p&gt;Here’s what it suggested:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin master
git pull origin master
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Your new commit message"&lt;/span&gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that, my local and remote were finally friends again. No force, no loss of files, and no broken history. The key? Don’t push through the problem — pull and merge into it instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moral of the Story
&lt;/h2&gt;

&lt;p&gt;The CLI can feel like a sword sometimes. Wield it well, and you feel powerful. Misuse it, and you're cleaning up history with a teaspoon. But moments like this are valuable. They teach us humility, patience, and the importance of taking a breath before smashing that &lt;code&gt;-f&lt;/code&gt; flag into existence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now I Want to Hear From You
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Has Git ever thrown off your coding groove?&lt;/li&gt;
&lt;li&gt;Have you ever used &lt;code&gt;git push -f&lt;/code&gt; and regretted it later?&lt;/li&gt;
&lt;li&gt;Do you always pull before pushing, or live on the edge?&lt;/li&gt;
&lt;li&gt;What’s your go-to Git strategy when conflicts or rejections arise?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop your stories in the comments — let’s normalize learning the hard way.&lt;/p&gt;

</description>
      <category>git</category>
      <category>push</category>
      <category>github</category>
      <category>origin</category>
    </item>
  </channel>
</rss>
