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