Kernel#then

obj.then { |x| block } -> result
Returns: Object · Added in v2.5 · Updated March 13, 2026 · Kernel Methods
blocks functional method-chaining

then passes the receiver to a block and returns the block’s result. It enables fluent method chaining on objects that don’t otherwise support it, letting you transform values in a pipeline style.

Syntax

object.then { |x| block } -> result

Parameters

ParameterTypeDescription
blockProcA block that receives the object and returns a transformed value

Examples

Basic transformation

# Square a number
5.then { |x| x * x }
# => 25

# Chain multiple transformations
10.then { |x| x + 1 }.then { |x| x * 2 }
# => 22

Method chaining with pipeline operator

# Ruby 3.0+ pipeline operator
1 |> then { |x| x + 10 } |> then { |x| x * 2 }
# => 22

# Equivalent using then
1.then { |x| x + 10 }.then { |x| x * 2 }
# => 22

Transforming data structures

# Convert hash to array of values
{ a: 1, b: 2 }.then { |h| h.values }
# => [1, 2]

# Transform and return the original type
[1, 2, 3].then { |arr| arr.map { |x| x * 2 } }
# => [2, 4, 6]

Common Patterns

Tap alternative

then is similar to tap but returns the block’s result instead of the receiver:

# tap returns self
result = "hello".tap { |s| s.upcase! }
# => "HELLO" (result is the modified string)

# then returns the block's value
result = "hello".then { |s| s.upcase }
# => "HELLO" (result is the upcased string)

Conditional transformation

user_input.then { |input| input.empty? ? nil : input.strip }

Object initialization pattern

# Build an object with transformations
User.new.then do |user|
  user.name = "Alice"
  user.email = "alice@example.com"
  user
end

Validation and transformation

# Validate then transform
data.then do |input|
  raise "Invalid" unless input.valid?
  input.to_json
end

Errors

then raises LocalJumpError if no block is given:

5.then
# => LocalJumpError: no block given

See Also