Skip to content

Instantly share code, notes, and snippets.

@lygaret
Last active June 9, 2022 08:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lygaret/117441fc5236de9f7d54b76894d69dec to your computer and use it in GitHub Desktop.
Save lygaret/117441fc5236de9f7d54b76894d69dec to your computer and use it in GitHub Desktop.
gem - string-inquirer
-m markdown
--private
--protected
--embed-mixins
--default-return void
**/*.rb
name version summary
string-inquirer
0.0.1
a small, simple mixin for string equality predicates

Adds methods to string which allows checking for string equality through arbitrary predicate methods.

Basically what Rails does in ActiveSupport, but packaged as a tiny gem.

Usage

Add this repo to your Gemfile:

gem "string-inquirer", "~> 0", git: "https://gist.github.com/117441fc5236de9f7d54b76894d69dec.git"

Then in your code:

runtime_mode = "development".freeze
runtime_mode = Accidental::StringInquirer.upgrade runtime_mode

"development".development? #=> NoMethodError
runtime_mode.development? #=> true
require "yaml"
header = YAML.safe_load_file("readme.md")
Gem::Specification.new do |spec|
spec.name = header["name"]
spec.version = header["version"]
spec.authors = ["Jon Raphaelson"]
spec.email = ["jon@accidental.cc"]
spec.summary = header["summary"]
spec.license = "MIT"
spec.files = Dir.glob("**/*.rb", base: __dir__)
spec.require_paths = ["."]
end
module Accidental
# Adds methods to strings which allows checking for string equality through
# arbitrary predicate methods;
#
# @example
# runtime_mode = "deploy".freeze
# runtime_mode = Accidental::StringInquirer.upgrade runtime_mode
#
# # predicate methods check for string equality
# runtime_mode.deploy? #=> true
# runtime_mode.development? #=> false
#
# # still a string, we add methods to the singleton class
# runtime_mode.class #=> String
# runtime_mode == "deploy" #=> true
module StringInquirer
# matches predicate looking methods
INQUIRER_FORMAT = /^(.+)\?$/
# a duplicate of the given string, with StringInquirer functionality mixed in.
# @return [String]
def self.upgrade(str)
raise ArgumentError, "must be a string!" unless str.is_a? String
str.dup.tap { _1.singleton_class.include StringInquirer }
end
# @param name [String] the method name to turn into a predicate check
# @return [String, nil] the string to check, or nil if not a predicate
def predicate_value(name)
match = INQUIRER_FORMAT.match name
match&.[](1)
end
# If the name of the missing method is a predicate (per {INQUIRER_FORMAT}),
# the return value will be the string equality of the method name with self.
#
# If the missing method is _not_ a predicate, keep going up the chain.
#
# @example
# foo = StringInquirer.upgrade "foo"
# "foo".development #=> NoMethodError
# "foo".development? #=> false ("foo" != "development")
# "foo".foo? #=> true ("foo" == "foo")
def method_missing(name, ...)
value = predicate_value(name.to_s)
return super(name, ...) if value.nil?
eql? value
end
def respond_to_missing?(name, incl_private = false)
predicate_value(name.to_s) ? true : super
end
end
end
require 'minitest/autorun'
require './string-inquirer'
describe Accidental::StringInquirer do
before do
@mode = "development"
@mode = Accidental::StringInquirer.upgrade(@mode)
end
it "should still be a string" do
assert_kind_of String, @mode
end
it "should respond to arbitrary predicates" do
assert_respond_to @mode, :whatever?
end
it "true when predicate matches the string" do
assert @mode.development?
end
it "false when predicate doesn't match the string" do
refute @mode.whatever?
end
it "can hand out a method" do
meth = @mode.method(:development?)
assert_kind_of Method, meth
assert meth.call
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment