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
| Parameter | Type | Description |
|---|---|---|
block | Proc | A 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