Method: Hanami::Utils::String.transform

Defined in:
lib/hanami/utils/string.rb

.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



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/hanami/utils/string.rb', line 121

def self.transform(input, *transformations)
  fn = @__transformations__.fetch_or_store(transformations.hash) do
    fns = Dry::Transformer::Function.new(->(object) { object })

    transformations.each do |transformation, *args|
      fns = fns.compose(
        if transformation.is_a?(Proc)
          transformation
        elsif contain?(transformation)
          self[transformation, *args]
        elsif input.respond_to?(transformation)
          ->(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

    fns
  end

  fn.call(input)
end