Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Most of the time we don't need to think about the environment our code is running in, because Ruby is designed to be a cross-platform language. However, certain tasks do require some system level operation, and in those situations, adapting to the user's environment can be tricky. An example of this can be seen in the way that HighLine implements its low level console interactions.
The HighLine library is designed to simplify the task of creating command line applications. While the library provides a lot of high level features, it is just as commonly used for some of its boring bits of functionality such as grabbing a single character of input from the user, or determining the dimensions of their console window. The reason why people turn to HighLine for these features rather than rolling their own is because HighLine does a good job at supporting a wide range of environments that are far from compatible with one another when it comes to console operations.
The approach HighLine takes to this problem is not especially pretty, but is fairly pragmatic. All of our system-dependent functionality is implemented in a single module called HighLine::SystemExtensions. This module attempts to identify the user's platform and available console tools through a rough combination of inspecting the
RUBY_PLATFORM constant and attempting to require commonly used libraries in a cascading fashion. Several different implementations of the same method are provided, but the conditions ensure that only the right one gets loaded for any given system. The end result is that no matter what environment the user runs HighLine in, the contract of
HighLine::SystemExtensions remains the same, even if it varies wildly in the way its methods are implemented.
In retrospect, this code from HighLine could be improved by giving each implementation its own module, and simply choosing the right module based on the profile matching criteria. However, the core idea would be the same: an interface would exist between HighLine's high level operations and its system interactions. This approach isolates the rest of the system from platform-specific dependencies, and that makes it easier to adapt to new environments.
Turn the page if you're taking the linear tour, or feel free to jump around via the sidebar.