Build Status Gem License

String::Builder

Refinement of the core String class, extending it with class and instance methods for streamlined string construction.

Methods

There are four 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
foobar = 'foo'.build do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "foobar"
foo = 'foo'

foobar = foo.build do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "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
foobar = 'foo'

foobar.build! do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "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
foobar = String.build do |s|
  s << 'fii'
  s.gsub!('ii','oo')
  s << 'bar'
end

foobar #=> "foobar"
foobar = String.build 'foo' do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "foobar"
foobar = String.build 3 do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "3bar"
foo = 'foo'

foobar = String.build foo do |s|
  s << 'bop'
  s.gsub!('op','ar')
end

foobar #=> "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 |message|
      time = Time.now.strftime("[%H:%M:%Ss]")
      String.build time do |s|
        s << " (#{__FILE__})"
        s << " #{severity.to_s.upcase} » #{message}"
        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 |message|
      time = Time.now.strftime("[%H:%M:%Ss]")
      time.build do |s|
        s << " (#{__FILE__})"
        s << " #{severity.to_s.upcase} » #{message}"
        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.