String::Builder
Modified and extended port of the String::Builder IO-style initializer for the String class of the Crystal programming language in the form of a Ruby gem refinement module.
Methods
There are three new methods in this extension of the String class:
Instance methods
String#build
Takes a block yielding a new builder string, and appends the builder string to a duplicate of the original String object, self.
Examples
= 'foo'.build do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "foobar"
foo = 'foo'
= foo.build do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "foobar"
String#build!
Takes a block yielding a new builder string, and appends the builder string to the original String object, self.
NOTE: This mutates the original string, as indicated by the bang !.
Example
= 'foo'
.build! do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "foobar"
Class methods
String.build
Takes an arbitrary object and a block yielding a new string builder, and appends the builder string to a duplicate of the object parameter converted to a string (with to_s).
If no block is given, then the object converted to a string (with to_s) is returned.
Examples
= String.build do |s|
s << 'fii'
s.gsub!('ii','oo')
s << 'bar'
end
#=> "foobar"
= String.build 'foo' do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "foobar"
= String.build 3 do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "3bar"
foo = 'foo'
= String.build foo do |s|
s << 'bop'
s.gsub!('op','ar')
end
#=> "foobar"
foo #=> "foo"
String.[]
Takes arbitrarily many objects (with splat), converts them to strings and contatenates them (takes the product with the empty string).
Examples
String[] #=> ""
String[3] #=> "3"
String['Hello','World','!'] #=> "HelloWorld!"
String[{k: 'v'}, 3, %i[a b c]] #=> "{:k=>\"v\"}3[:a, :b, :c]"
String[*['a', 2, :z]] #=> "a2z"
Detailed example
This example shows how to make a simple logger by constructing log messages with String::Builder.
Suppose we want a Logger class that allows us to do the following:
logger = Logger.new
logger.error 'String::Builder is good?'
#=> [03:54:53s] (lib/string-builder.rb) ERROR » String::Builder is good!
logger.success 'String::Builder is good?'
#=> [03:54:55s] (lib/string-builder.rb) SUCCESS » String::Builder is good!
logger.info 'String::Builder is good?'
#=> [03:54:57s] (lib/string-builder.rb) INFO » String::Builder is good!
logger.warning 'String::Builder is good?'
#=> [03:54:59s] (lib/string-builder.rb) WARNING » String::Builder is good!
Class method - String.build
require 'string/builder'
class Logger
using String::Builder
%i[error success info warning].each do |severity|
define_method(severity) do ||
time = Time.now.strftime("[%H:%M:%Ss]")
String.build time do |s|
s << " (#{__FILE__})"
s << " #{severity.to_s.upcase} » #{}"
s.gsub!('?','!')
end
end
end
end
Instance method - String#build
The class shown above can use the String#build instance method to achieve the same functionality.
require 'string/builder'
class Logger
using String::Builder
%i[error success info warning].each do |severity|
define_method(severity) do ||
time = Time.now.strftime("[%H:%M:%Ss]")
time.build do |s|
s << " (#{__FILE__})"
s << " #{severity.to_s.upcase} » #{}"
s.gsub!('?','!')
end
end
end
end
Installation
Add this line to your application's Gemfile:
gem 'string-builder'
And then execute:
$ bundle
Or install it yourself as:
$ gem install string-builder
Usage
This extension is in the form of a refinement. This means that you will have to call the following using directive within the scope that you want the String class to be extended with String::Builder methods:
require 'string/builder'
using String::Builder
Though you should typically avoid doing this in the global scope (unless you really need to), and instead only use the extension where you need it - inside your specific modules or classes:
require 'string/builder'
class A
using String::Builder
# CAN use String::Builder methods in this class
end
module B
# CANNOT use String::Builder methods in this module
end
# CANNOT use String::Builder methods in the global scope
Further information
For more information about string-building in Ruby and Crystal, read this blog post.