Class: Hanami::Utils::String

Inherits:
Object
  • Object
show all
Extended by:
Transproc::Composer, Transproc::Registry
Defined in:
lib/hanami/utils/string.rb

Overview

String on steroids

Since:

  • 0.1.0

Direct Known Subclasses

PathPrefix

Constant Summary collapse

EMPTY_STRING =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Empty string for #classify

Since:

  • 0.6.0

""
NAMESPACE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator between Ruby namespaces

Since:

  • 0.1.0

"::"
CLASSIFY_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #classify

Since:

  • 0.3.0

"_"
TOKENIZE_REGEXP =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regexp for #tokenize

Since:

  • 0.3.0

/\((.*)\)/.freeze
TOKENIZE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #tokenize

Since:

  • 0.3.0

"|"
UNDERSCORE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #underscore

Since:

  • 0.3.0

"/"
UNDERSCORE_DIVISION_TARGET =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

gsub second parameter used in #underscore

Since:

  • 0.3.0

'\1_\2'
TITLEIZE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #titleize

Since:

  • 0.4.0

" "
CAPITALIZE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #capitalize

Since:

  • 0.5.2

" "
DASHERIZE_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Separator for #dasherize

Since:

  • 0.4.0

"-"
CLASSIFY_WORD_SEPARATOR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Regexp for #classify

Since:

  • 0.3.4

/#{CLASSIFY_SEPARATOR}|#{NAMESPACE_SEPARATOR}|#{UNDERSCORE_SEPARATOR}|#{DASHERIZE_SEPARATOR}/.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ Hanami::Utils::String

Deprecated.

Initialize the string

Parameters:

  • string (::String, Symbol)

    the value we want to initialize

Since:

  • 0.1.0



394
395
396
# File 'lib/hanami/utils/string.rb', line 394

def initialize(string)
  @string = string.to_s
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &blk) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Overrides Ruby’s method_missing in order to provide ::String interface

Raises:

  • (NoMethodError)

    If doesn’t respond to the given method

Since:

  • 0.3.0



732
733
734
735
736
737
738
739
740
# File 'lib/hanami/utils/string.rb', line 732

def method_missing(method_name, *args, &blk)
  unless respond_to?(method_name)
    raise NoMethodError.new(%(undefined method `#{method_name}' for "#{@string}":#{self.class}))
  end

  s = @string.__send__(method_name, *args, &blk)
  s = self.class.new(s) if s.is_a?(::String)
  s
end

Class Method Details

.bind(value, binding, fun) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Extracted from transproc source code

transproc is Copyright 2014 by Piotr Solnica ([email protected]), released under the MIT License

Since:

  • 1.1.0



162
163
164
# File 'lib/hanami/utils/string.rb', line 162

def self.bind(value, binding, fun)
  binding.instance_exec(value, &fun)
end

.capitalize(input) ⇒ ::String

Returns a capitalized version of the string

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.capitalize('hanami') # => "Hanami"

Hanami::Utils::String.capitalize('hanami utils') # => "Hanami utils"

Hanami::Utils::String.capitalize('Hanami Utils') # => "Hanami utils"

Hanami::Utils::String.capitalize('hanami_utils') # => "Hanami utils"

Hanami::Utils::String.capitalize('hanami-utils') # => "Hanami utils"

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

Since:

  • 1.1.0



203
204
205
206
207
208
# File 'lib/hanami/utils/string.rb', line 203

def self.capitalize(input)
  string = ::String.new(input.to_s)
  head, *tail = underscore(string).split(CLASSIFY_SEPARATOR)

  tail.unshift(head.capitalize).join(CAPITALIZE_SEPARATOR)
end

.classify(input) ⇒ ::String

Returns a CamelCase version of the string

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.classify('hanami_utils') # => 'HanamiUtils'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

Since:

  • 1.1.0



222
223
224
225
226
227
228
229
230
231
232
# File 'lib/hanami/utils/string.rb', line 222

def self.classify(input)
  string = ::String.new(input.to_s)
  words = underscore(string).split(CLASSIFY_WORD_SEPARATOR).map!(&:capitalize)
  delimiters = underscore(string).scan(CLASSIFY_WORD_SEPARATOR)

  delimiters.map! do |delimiter|
    delimiter == CLASSIFY_SEPARATOR ? EMPTY_STRING : NAMESPACE_SEPARATOR
  end

  words.zip(delimiters).join
end

.dasherize(input) ⇒ Object

Hanami::Utils::String.dasherize(‘hanami_utils’) # => ‘hanami-utils’

Hanami::Utils::String.dasherize('HanamiUtils') # => "hanami-utils"

Since:

  • 0.1.0



275
276
277
278
# File 'lib/hanami/utils/string.rb', line 275

def self.dasherize(input)
  string = ::String.new(input.to_s)
  underscore(string).split(CLASSIFY_SEPARATOR).join(DASHERIZE_SEPARATOR)
end

.demodulize(input) ⇒ ::String

Returns the string without the Ruby namespace of the class

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.demodulize('Hanami::Utils::String') # => 'String'

Hanami::Utils::String.demodulize('String') # => 'String'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

Since:

  • 1.1.0



294
295
296
# File 'lib/hanami/utils/string.rb', line 294

def self.demodulize(input)
  ::String.new(input.to_s).split(NAMESPACE_SEPARATOR).last
end

.namespace(input) ⇒ ::String

Returns the top level namespace name

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.namespace('Hanami::Utils::String') # => 'Hanami'

Hanami::Utils::String.namespace('String') # => 'String'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

Since:

  • 1.1.0



312
313
314
# File 'lib/hanami/utils/string.rb', line 312

def self.namespace(input)
  ::String.new(input.to_s).split(NAMESPACE_SEPARATOR).first
end

.pluralize(input) ⇒ ::String

Deprecated.

Returns a pluralized version of self.

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.pluralize('book') # => 'books'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the pluralized string.

See Also:

Since:

  • 1.1.0



331
332
333
334
# File 'lib/hanami/utils/string.rb', line 331

def self.pluralize(input)
  string = ::String.new(input.to_s)
  Inflector.pluralize(string)
end

.rsub(input, pattern, replacement) ⇒ ::String

Replaces the rightmost match of pattern with replacement

If the pattern cannot be matched, it returns the original string.

This method does NOT mutate the original string.

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.rsub('authors/books/index', %r{/}, '#')
  # => 'authors/books#index'

Parameters:

  • input (::String)

    the input

  • pattern (Regexp, ::String)

    the pattern to find

  • replacement (String)

    the string to replace

Returns:

  • (::String)

    the replaced string

Since:

  • 1.1.0



375
376
377
378
379
380
381
382
383
384
# File 'lib/hanami/utils/string.rb', line 375

def self.rsub(input, pattern, replacement)
  string = ::String.new(input.to_s)
  if i = string.rindex(pattern)
    s = string.dup
    s[i] = replacement
    s
  else
    string
  end
end

.singularize(input) ⇒ ::String

Deprecated.

Returns a singularized version of self.

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.singularize('books') # => 'book'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the singularized string.

See Also:

Since:

  • 1.1.0



351
352
353
354
# File 'lib/hanami/utils/string.rb', line 351

def self.singularize(input)
  string = ::String.new(input.to_s)
  Inflector.singularize(string)
end

.titleize(input) ⇒ ::String

Returns a titleized version of the string

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.titleize('hanami utils') # => "Hanami Utils"

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

Since:

  • 1.1.0



178
179
180
181
# File 'lib/hanami/utils/string.rb', line 178

def self.titleize(input)
  string = ::String.new(input.to_s)
  underscore(string).split(CLASSIFY_SEPARATOR).map(&:capitalize).join(TITLEIZE_SEPARATOR)
end

.transform(input, *transformations) ⇒ ::String

Applies the given transformation(s) to input

It performs a pipeline of transformations, by applying the given functions from Hanami::Utils::String and ::String. The transformations are applied in the given order.

It doesn’t mutate the input, unless you use destructive methods from ::String

Examples:

Basic usage

require "hanami/utils/string"

Hanami::Utils::String.transform("hanami/utils", :underscore, :classify)
  # => "Hanami::Utils"

Hanami::Utils::String.transform("Hanami::Utils::String", [:gsub, /[aeiouy]/, "*"], :demodulize)
  # => "H*n*m*"

Hanami::Utils::String.transform("Hanami", ->(s) { s.upcase })
  # => "HANAMI"

Unkown transformation

require "hanami/utils/string"

Hanami::Utils::String.transform("Sakura", :foo)
  # => NoMethodError: undefined method `:foo' for "Sakura":String

Proc with arity not equal to 1

require "hanami/utils/string"

Hanami::Utils::String.transform("Cherry", -> { "blossom" }))
  # => ArgumentError: wrong number of arguments (given 1, expected 0)

Parameters:

  • input (::String)

    the string to be transformed

  • transformations (Array<Symbol,Proc,Array>)

    one or many transformations expressed as:

    * `Symbol` to reference a function from `Hanami::Utils::String` or `String`.
    * `Proc` an anonymous function that MUST accept one input
    * `Array` where the first element is a `Symbol` to reference a
      function from `Hanami::Utils::String` or `String` and the rest of
      the elements are the arguments to pass
    

Returns:

  • (::String)

    the result of the transformations

Raises:

  • (NoMethodError)

    if a Hanami::Utils::String and ::String don’t respond to a given method name

  • (ArgumentError)

    if a Proc transformation has an arity not equal to 1

Since:

  • 1.1.0



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/hanami/utils/string.rb', line 135

def self.transform(input, *transformations)
  fn = @__transformations__.fetch_or_store(transformations.hash) do
    compose do |fns|
      transformations.each do |transformation, *args|
        fns << if transformation.is_a?(Proc)
                 transformation
               elsif contain?(transformation)
                 self[transformation, *args]
               elsif input.respond_to?(transformation)
                 t(:bind, input, ->(i) { i.public_send(transformation, *args) })
               else
                 raise NoMethodError.new(%(undefined method `#{transformation.inspect}' for #{input.inspect}:#{input.class})) # rubocop:disable Layout/LineLength
               end
      end
    end
  end

  fn.call(input)
end

.underscore(input) ⇒ ::String

Returns a downcased and underscore separated version of the string

Revised version of ActiveSupport::Inflector.underscore implementation

Examples:

require 'hanami/utils/string'

Hanami::Utils::String.underscore('HanamiUtils') # => 'hanami_utils'

Parameters:

  • input (::String)

    the input

Returns:

  • (::String)

    the transformed string

See Also:

Since:

  • 1.1.0



249
250
251
252
253
254
255
256
257
# File 'lib/hanami/utils/string.rb', line 249

def self.underscore(input)
  string = ::String.new(input.to_s)
  string.gsub!(NAMESPACE_SEPARATOR, UNDERSCORE_SEPARATOR)
  string.gsub!(NAMESPACE_SEPARATOR, UNDERSCORE_SEPARATOR)
  string.gsub!(/([A-Z\d]+)([A-Z][a-z])/, UNDERSCORE_DIVISION_TARGET)
  string.gsub!(/([a-z\d])([A-Z])/, UNDERSCORE_DIVISION_TARGET)
  string.gsub!(/[[:space:]]|\-/, UNDERSCORE_DIVISION_TARGET)
  string.downcase
end

Instance Method Details

#==(other) ⇒ TrueClass, FalseClass Also known as: eql?

Deprecated.

Equality

Returns:

  • (TrueClass, FalseClass)

Since:

  • 0.3.0



644
645
646
# File 'lib/hanami/utils/string.rb', line 644

def ==(other)
  to_s == other
end

#capitalizeHanami::Utils::String

Deprecated.

Returns a capitalized version of the string

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'hanami'
string.capitalize # => "Hanami"

string = Hanami::Utils::String.new 'hanami utils'
string.capitalize # => "Hanami utils"

string = Hanami::Utils::String.new 'Hanami Utils'
string.capitalize # => "Hanami utils"

string = Hanami::Utils::String.new 'hanami_utils'
string.capitalize # => "Hanami utils"

string = Hanami::Utils::String.new 'hanami-utils'
string.capitalize # => "Hanami utils"

Returns:

Since:

  • 0.5.2



438
439
440
441
442
443
444
# File 'lib/hanami/utils/string.rb', line 438

def capitalize
  head, *tail = underscore.split(CLASSIFY_SEPARATOR)

  self.class.new(
    tail.unshift(head.capitalize).join(CAPITALIZE_SEPARATOR)
  )
end

#classifyHanami::Utils::String

Deprecated.

Use classify

Returns a CamelCase version of the string

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'hanami_utils'
string.classify # => 'HanamiUtils'

Returns:

Since:

  • 0.1.0



458
459
460
461
462
463
464
465
466
467
# File 'lib/hanami/utils/string.rb', line 458

def classify
  words = underscore.split(CLASSIFY_WORD_SEPARATOR).map!(&:capitalize)
  delimiters = underscore.scan(CLASSIFY_WORD_SEPARATOR)

  delimiters.map! do |delimiter|
    delimiter == CLASSIFY_SEPARATOR ? EMPTY_STRING : NAMESPACE_SEPARATOR
  end

  self.class.new words.zip(delimiters).join
end

#dasherizeHanami::Utils::String

Deprecated.

Use dasherize

Returns a downcased and dash separated version of the string

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'Hanami Utils'
string.dasherize # => 'hanami-utils'

string = Hanami::Utils::String.new 'hanami_utils'
string.dasherize # => 'hanami-utils'

string = Hanami::Utils::String.new 'HanamiUtils'
string.dasherize # => "hanami-utils"

Returns:

Since:

  • 0.4.0



511
512
513
# File 'lib/hanami/utils/string.rb', line 511

def dasherize
  self.class.new underscore.split(CLASSIFY_SEPARATOR).join(DASHERIZE_SEPARATOR)
end

#demodulizeHanami::Utils::String

Deprecated.

Returns the string without the Ruby namespace of the class

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'Hanami::Utils::String'
string.demodulize # => 'String'

string = Hanami::Utils::String.new 'String'
string.demodulize # => 'String'

Returns:

Since:

  • 0.1.0



530
531
532
# File 'lib/hanami/utils/string.rb', line 530

def demodulize
  self.class.new split(NAMESPACE_SEPARATOR).last
end

#gsub(pattern, replacement = nil, &blk) ⇒ ::String

Deprecated.

Replaces the given pattern with the given replacement

Returns:

  • (::String)

See Also:

Since:

  • 0.3.0



670
671
672
673
674
675
676
# File 'lib/hanami/utils/string.rb', line 670

def gsub(pattern, replacement = nil, &blk)
  if block_given?
    @string.gsub(pattern, &blk)
  else
    @string.gsub(pattern, replacement)
  end
end

#hashInteger

Deprecated.

Returns the hash of the internal string

Returns:

  • (Integer)

Since:

  • 0.3.0



622
623
624
# File 'lib/hanami/utils/string.rb', line 622

def hash
  @string.hash
end

#namespaceHanami::Utils::String

Deprecated.

Use namespace

Returns the top level namespace name

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'Hanami::Utils::String'
string.namespace # => 'Hanami'

string = Hanami::Utils::String.new 'String'
string.namespace # => 'String'

Returns:

Since:

  • 0.1.2



549
550
551
# File 'lib/hanami/utils/string.rb', line 549

def namespace
  self.class.new split(NAMESPACE_SEPARATOR).first
end

#pluralizeHanami::Utils::String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Deprecated.

Returns a pluralized version of self.

Returns:

See Also:

Since:

  • 0.4.1



599
600
601
# File 'lib/hanami/utils/string.rb', line 599

def pluralize
  self.class.new Inflector.pluralize(self)
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Overrides Ruby’s respond_to_missing? in order to support ::String interface

Returns:

Since:

  • 0.3.0



746
747
748
# File 'lib/hanami/utils/string.rb', line 746

def respond_to_missing?(method_name, include_private = false)
  @string.respond_to?(method_name, include_private)
end

#rsub(pattern, replacement) ⇒ Hanami::Utils::String

Deprecated.

Use rsub

Replaces the rightmost match of pattern with replacement

If the pattern cannot be matched, it returns the original string.

This method does NOT mutate the original string.

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new('authors/books/index')
result = string.rsub(/\//, '#')

puts string
  # => #<Hanami::Utils::String:0x007fdb41233ad8 @string="authors/books/index">

puts result
  # => #<Hanami::Utils::String:0x007fdb41232ed0 @string="authors/books#index">

Parameters:

Returns:

Since:

  • 0.6.0



716
717
718
719
720
721
722
723
724
# File 'lib/hanami/utils/string.rb', line 716

def rsub(pattern, replacement)
  if i = rindex(pattern)
    s    = @string.dup
    s[i] = replacement
    self.class.new s
  else
    self
  end
end

#scan(pattern, &blk) ⇒ Array<::String>

Deprecated.

Iterates through the string, matching the pattern. Either return all those patterns, or pass them to the block.

Returns:

  • (Array<::String>)

See Also:

Since:

  • 0.6.0



687
688
689
# File 'lib/hanami/utils/string.rb', line 687

def scan(pattern, &blk)
  @string.scan(pattern, &blk)
end

#singularizeHanami::Utils::String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Deprecated.

Returns a singularized version of self.

Returns:

See Also:

Since:

  • 0.4.1



612
613
614
# File 'lib/hanami/utils/string.rb', line 612

def singularize
  self.class.new Inflector.singularize(self)
end

#split(pattern, limit = 0) ⇒ Array<::String>

Deprecated.

Splits the string with the given pattern

Returns:

  • (Array<::String>)

See Also:

Since:

  • 0.3.0



658
659
660
# File 'lib/hanami/utils/string.rb', line 658

def split(pattern, limit = 0)
  @string.split(pattern, limit)
end

#titleizeHanami::Utils::String

Deprecated.

Use titleize

Returns a titleized version of the string

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'hanami utils'
string.titleize # => "Hanami Utils"

Returns:

Since:

  • 0.4.0



410
411
412
# File 'lib/hanami/utils/string.rb', line 410

def titleize
  self.class.new underscore.split(CLASSIFY_SEPARATOR).map(&:capitalize).join(TITLEIZE_SEPARATOR)
end

#to_s::String Also known as: to_str

Deprecated.

Returns a string representation

Returns:

  • (::String)

Since:

  • 0.3.0



632
633
634
# File 'lib/hanami/utils/string.rb', line 632

def to_s
  @string
end

#tokenize { ... } ⇒ void

Deprecated.

This method returns an undefined value.

It iterates through the tokens and calls the given block. A token is a substring wrapped by ‘()` and separated by `|`.

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'Hanami::(Utils|App)'
string.tokenize do |token|
  puts token
end

# =>
  'Hanami::Utils'
  'Hanami::App'

Yields:

  • the block that is called for each token.

Since:

  • 0.1.0



575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'lib/hanami/utils/string.rb', line 575

def tokenize
  if match = TOKENIZE_REGEXP.match(@string)
    pre  = match.pre_match
    post = match.post_match
    tokens = match[1].split(TOKENIZE_SEPARATOR)
    tokens.each do |token|
      yield(self.class.new("#{pre}#{token}#{post}"))
    end
  else
    yield(self.class.new(@string))
  end

  nil
end

#underscoreHanami::Utils::String

Deprecated.

Returns a downcased and underscore separated version of the string

Revised version of ActiveSupport::Inflector.underscore implementation

Examples:

require 'hanami/utils/string'

string = Hanami::Utils::String.new 'HanamiUtils'
string.underscore # => 'hanami_utils'

Returns:

See Also:

Since:

  • 0.1.0



484
485
486
487
488
489
490
491
# File 'lib/hanami/utils/string.rb', line 484

def underscore
  new_string = gsub(NAMESPACE_SEPARATOR, UNDERSCORE_SEPARATOR)
  new_string.gsub!(/([A-Z\d]+)([A-Z][a-z])/, UNDERSCORE_DIVISION_TARGET)
  new_string.gsub!(/([a-z\d])([A-Z])/, UNDERSCORE_DIVISION_TARGET)
  new_string.gsub!(/[[:space:]]|\-/, UNDERSCORE_DIVISION_TARGET)
  new_string.downcase!
  self.class.new new_string
end