Kernel#p
p(object) -> object The p method outputs objects to STDOUT using their inspect method, making it ideal for debugging. Unlike puts which calls to_s, p shows the actual structure of objects.
Basic usage
# Simple values
p "hello" # => "hello"
p 42 # => 42
p [1, 2, 3] # => [1, 2, 3]
# Returns the object
result = p [1, 2, 3]
# Prints: [1, 2, 3]
# Returns: [1, 2, 3]
The p method calls inspect on its argument, revealing quotes around strings and the internal representation of arrays and hashes. This makes it ideal for debugging when you need to see the exact object structure rather than a user-friendly display, and it is why experienced Ruby developers reach for p over puts during development.
p vs puts vs print
# puts calls to_s
puts "hello" # hello (no quotes)
puts [1, 2] # 1
# 2
# p calls inspect
p "hello" # "hello" (with quotes)
p [1, 2] # [1, 2]
# print is like puts but no newline
print "hi" # hi (no newline)
The p method is especially useful for inspecting data structures that contain mixed types. When you pass an array or hash to p, you see the full nested structure with all types preserved, which is exactly the information you need when debugging unexpected behaviour in your collections.
Practical examples
Debugging Arrays
data = [1, "hello", {key: "value"}]
p data
# Output: [1, "hello", {:key=>"value"}]
# (shows the actual structure)
p works on any Ruby object by calling inspect, so the output format depends on the object’s class. Hashes display with the rocket syntax in the inspect form, while strings show their surrounding quotes and numbers appear as bare integers or floats.
Debugging Hashes
config = { debug: true, port: 8080 }
p config
# Output: {:debug=>true, :port=>8080}
When you pass several arguments to p, each one is printed on its own line. This keeps the output readable even when the individual values are long or nested, and you can see each argument’s type and contents at a glance.
Multiple Arguments
# p accepts multiple arguments
x = 10
p x, x*2, x*3
# Output:
# 10
# 20
# 30
Using p inside a method body lets you trace the value of a variable at different points in the computation. Because p returns its argument, you can insert it into a method chain without changing the data flow, which is especially useful when debugging pipeline-style code.
In Methods
def process_data(input)
p input # Debug print
# ... process
p input # Debug print after
end
Custom objects printed with p show their class name, object ID, and instance variables. This is the richest form of debugging output available without writing a custom inspect method, and it helps you verify that object state matches your expectations at each step.
With Objects
class User
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
user = User.new("Alice", 30)
p user
# Output: #<User:0x00007f8a2c003a80 @name="Alice", @age=30>
Since p returns its argument, you can wrap it around any expression to inspect the value mid-computation. This is helpful when you need to check an intermediate result without restructuring the surrounding code. The return-value behaviour also means you can nest p calls or chain them with other methods.
Chaining
# p returns its argument, so it can be chained
result = p p [1, 2, 3]
# Prints:
# [1, 2, 3]
# [1, 2, 3]
# Returns: [1, 2, 3]
In an interactive Ruby console, p is the fastest way to inspect a variable’s contents without calling methods on it. Just type p object and you see the full structure laid out on one line, which is why it is a staple of REPL-driven development.
IRB/Console debugging
# In IRB or Rails console
p variables
p params
p ENV["PATH"]
Quick debugging output
p is the fastest way to see what an object really looks like while a program is running. It prints the inspect form, which means quotes, hash rockets, and object details stay visible instead of being flattened into a friendlier string. That makes it especially useful when you are checking data structures in the console or tracing a small bug in development. Because p returns the object it prints, it also fits neatly into short debugging chains without changing the value being passed along.
It is also a good choice when you want the output to show exactly what Ruby sees, not a polished message for an end user. That makes it a reliable tool for quick logging during development, especially when an array or hash needs to be checked in place. If the program needs a more structured log later, p can help you understand the shape first and then move the message into a dedicated logger once the behavior is clear.
The main habit to keep is restraint: use p while you are learning what the object contains, then replace it once the code is stable. That way the final program does not depend on debug noise, but the development loop still has a simple way to reveal the exact value at the right moment.
If you pair p with small helper methods, the output can stay focused without hiding the rest of the flow. That often works well in console work or quick scripts where the real goal is to understand the object, not to build a permanent log format. Once the shape is clear, the debug prints can disappear cleanly.
Use cases
- Debugging variable values
- Inspecting complex data structures
- Quick logging during development
- Seeing exact object types