- Key Takeaways
- Make use of gem authoring tools
- Use load paths and require responsibly
- Don’t require rubygems inside your gem
- Use a meaningful versioning pattern
- Harness the power of Bundler for testing
- Have a decent way to track issues publicly
- Make contributing easy
- Once public, it stays public
- Naming and casing
- Wrapping up
- Frequently Asked Questions about Crafting Rubies and Best Practices
To some, cutting gems is considered an art for the minerally inclined. In the Ruby world, however, gem cutting is a matter of life. Creating RubyGems can be easy, but also a trap for a novice. By following some general community best practices, you can create gems that can live in harmony within the Ruby ecosystem, and be enjoyed by consumers and contributors alike for years to come.
Key Takeaways
- Utilize gem authoring tools like Jeweler to automate most of the manual work involved in publishing gems, making the process easier and less prone to beginner errors.
- Ensure responsible use of load paths and require in Ruby, avoiding dependencies outside of your project’s lib/ folder and not requiring ‘rubygems’ inside your gem to allow users the choice of package manager.
- Adopt meaningful versioning patterns, harness Bundler for testing, provide a public way to track issues, make contributing easy, and remember that once a gem is public, it stays public.
Make use of gem authoring tools
With the exception of experienced cutters, or those who want or need to have complete control over every line of code, there are gem authoring tools that can automate the majority of the manual work required, and avoid amateur mistakes, when publishing gems for the first time.
The biggest of the gem authoring tools at the moment is Jeweler (RubyGems, GitHub), which aims to provide a set of wizard based gem automation tools. It has tasks to manage releasing, versioning, dependencies, executables and Rake tasks all out of the box; it can be a real time saver in the long run for frequent or beginner gem publishers.
Use load paths and require
responsibly
It’s very easy to clobber the load path or use require
horribly in Ruby without realising the detriments of doing so. A fantastic article by Josh Peek on the Ruby on Rails blog details the ins and outs of the load path and require’ing, which is well worth the reading time. Some of the more important points of his article are:
- RubyGems (and most other package managers) add the
lib/
directory of your gem to the load path; in some cases this is prepended to the load path. If yourlib/
directory contains any files named the same as any core Ruby files (eg.string.rb
), your gems’ file will take precedence. As such, follow the convention to keep all your files under a directory named the same as your gem within yourlib/
folder, eg.lib/gem_name/something.rb
. - Most package managers, and testing frameworks, will automatically add your
lib/
and test folders (spec/
andfeatures/
being two examples) to the load path. If providing an executable, or aRakefile
, you can add thelib/
directory to the path there ($:.unshift(path_to_lib)
). As a result, remove code using things likeFile.dirname(__FILE__)
within any requires, as you can safely assume that you can always require relative to yourlib/
directory. Don’t depend on anything outside of your project’s
lib/
folder (with the exception of other gems); some package managers only copy across yourlib/
directory.
├── test_gem.gemspec
├── Gemfile
├── Rakefile
├── README
├── bin
│ └── test_gem
├── lib
│ ├── test_gem
│ │ └── some_module_or_class.rb
│ └── test_gem.rb
└── spec/features/test
└── *
Don’t require rubygems inside your gem
When you include require 'rubygems'
in your gem, you take away the user’s choice to use a package manager other than RubyGems. There are many powerful and full featured alternatives to RubyGems, including Rip (RubyGems, GitHub), and Dpkg (used mainly by sysadmins who need to manage gems using Debian packages).
Ryan Tomayko has a brilliant article on his blog entitled ‘Why “require ‘rubygems'” is wrong”, which details the technical reasoning and best practices behind leaving it out.
Use a meaningful versioning pattern
Versioning gems can be a painful experience, but it’s a mountain that has been conquered by very intelligent people (several times at that). The Semantic Versioning system aims to make versioning more predictable, and therefore safer, and it can be applied to gems with minimal effort. The semver.org website includes a detailed specification, as well as best practices when versioning software.
Some important takeaway points from the specification are:
- Versions should be in the format X.Y.Z (Major.Minor.Patch).
- You can use special version numbers when pushing out test release versions, eg. 1.0.0beta1, 1.0.0alpha3, 1.0.0rc1.
- You can make feature changes and bug fixes in Major versions.
- You can make backwards compatible feature changes and bug fixes in Minor versions.
- You can only make backwards compatible bug fixes in Patch versions.
- The API should be considered public and stable from 1.0.0 and onwards.
Harness the power of Bundler for testing
A little known secret of Bundler is that it can automatically use the dependencies within your .gemspec
file, whether manually provided or generated by a gem tool, to create a Gemfile
.
source :rubygems
gemspec
With the simplest of Gemfile
s above, you can distribute an easily maintained Gemfile.lock
, and use bundle exec
to wrap your test runs and prevent gem version collisions.
Have a decent way to track issues publicly
Creating a gem without any issues is a myth. However, remembering that most of the users of any gems you create will also be technically adept, it’s a matter of course that you will have people who are ready and willing with the required details for providing a fix.
Providing a decent way of tracking issues seems obvious, but you’d be surprised at how difficult it can be to find a place to submit bugs, feature requests, or other issues to some gem maintainers.
If you’re hosting your gem on GitHub, you get a fantastic issue tracker for free. Some people prefer hosting on things like Lighthouse; whatever you choose, just make sure it’s linked to within the README in an obvious way.
Make contributing easy
Tangential to the last point is the idea that contributing to a gem should be easy. Make sure that you have a clear license that explains what and how people are allowed to contribute. Also try to make it worth their while to contribute back to the original code by offering clear instructions and restrictions that you apply to any incoming source code.
Hosting your code on GitHub is a fantastic way to nurture this practice, as Git makes it dead simple to work in a fork-alter-merge pattern, and GitHub wraps this in Pull Request goodness.
GitHub has a great help section on Pull Requests which should prove invaluable to Git/GitHub newcomers.
Once public, it stays public
Once you’ve published a gem, even if you’ve made a catastrophic mistake, it should be your absolutely last resort to yank the gem. Even more important is that, if you do finding yourself having to yank a version, under no circumstances should you reuse the version number of the copy you yanked.
System administrators, and developers for that matter, rely heavily on gem numbers being immutable and ever available. Even if you have added a password or other piece of important security information that you need removed, you’re likely better just to change the password (you’ll need to do this anyway), and publish a follow-up release.
The help section at RubyGems has a very detailed set of instructions on gem yanking should you, for whatever reason, still feel you need to exercise this right to arms.
Naming and casing
Naming is probably the first thing you will find yourself doing, and perhaps one of the most important steps you need to get right.
Before getting your heart set on a particular name, be sure to check RubyGems.org and GitHub and make sure your name isn’t taken.
There are some commonly adhered to rules about casing, which you shouldn’t break unless you really have a good reason. The following rules apply to the name of the gem, as well as any file names within the gem:
- No upper-case letters. This will inevitably cause problems for users on Windows or OS X, which both use case insensitive file systems by default.
- Use underscores for spaces. An example, “Test Class” should become “test_class”.
- Try to keep one module or class per file, and name the file after that module or class. An example, if a file contains a module called “EventGenerator”, the file should be called “event_generator”.
If you follow these pretty simple rules, all of a sudden it becomes a lot easier for people to make assumptions about how to gem install
, require
, and contribute to your code; a little effort here goes a long way.
Wrapping up
So you want to create your own gems? By following the above best practices, you’re likely to avoid treading on the toes of your forebearers. A lot of very smart, very intelligent people are responsible for making gem cutting as easy as it is today, and in the process they offer valuable tools and techniques that require some level of mastery. Learn these tools, follow the best practices above, and you’ll be on your way to helping create a safer, cleaner and more efficient Ruby code community.
Frequently Asked Questions about Crafting Rubies and Best Practices
What are the best practices for cutting rubies?
Cutting rubies requires a high level of expertise and precision. The best practices include understanding the ruby’s crystal structure, determining the optimal cut for the gemstone, and using the right tools. The cutter should also consider the ruby’s color, clarity, and carat weight. The goal is to maximize the ruby’s beauty and value while minimizing waste.
How can I determine the quality of a ruby?
The quality of a ruby is determined by its color, clarity, cut, and carat weight, also known as the 4Cs. The most valuable rubies have a pure, vibrant red to slightly purplish red color. As for clarity, rubies that are free of inclusions are the most prized. The cut of the ruby should enhance its color and brilliance. Lastly, larger rubies are rarer and more valuable.
What tools are needed to cut rubies?
Cutting rubies requires specialized tools. These include a gem cutting machine, a dop stick, a lap (a disc coated with a cutting or polishing compound), and a loupe or microscope to inspect the gemstone. Safety equipment such as goggles and a dust mask are also essential.
What are the different cuts for rubies?
Rubies can be cut into various shapes, including round, oval, cushion, emerald, and pear. The choice of cut depends on the ruby’s shape and size, as well as the cutter’s skill and the desired final appearance of the gemstone.
How can I care for my ruby gemstone?
Rubies are durable gemstones, but they still require proper care. Avoid exposing your ruby to harsh chemicals or extreme heat. Clean it with mild soap and warm water, and use a soft brush to remove any dirt. Store your ruby separately from other gemstones to prevent scratches.
What is the difference between natural and synthetic rubies?
Natural rubies are formed over millions of years under the Earth’s crust, while synthetic rubies are created in a laboratory. Although they have the same physical and chemical properties, natural rubies are more valuable due to their rarity.
How can I identify a synthetic ruby?
Identifying a synthetic ruby can be challenging without professional equipment. Synthetic rubies often have fewer inclusions and a more uniform color than natural rubies. If you’re unsure, it’s best to consult a gemologist.
What factors affect the value of a ruby?
The value of a ruby is determined by its color, clarity, cut, and carat weight. Other factors include its origin and whether it’s natural or synthetic. Rubies from Myanmar (formerly Burma) are considered the most valuable.
Can rubies be treated to improve their appearance?
Yes, rubies can be treated to enhance their color and clarity. Common treatments include heat treatment and fracture filling. However, treated rubies are less valuable than untreated ones.
What is the symbolism of rubies?
Rubies symbolize love, passion, courage, and power. They are also associated with good luck and protection. In ancient times, rubies were believed to possess magical powers.
Hi! I currently work for Intent HQ as Director of Engineering, writing functional Scala by day and Rust by night. I write for SitePoint about Ruby, and I’m on Twitter and on GitHub. You can get in touch with me at mail/at/nathankleyn.com.