Ruby ranges are a clean way to represent a sequence of values—most commonly numbers, letters, or dates. You’ll see ranges everywhere in Ruby, from loops to filtering arrays to case statements.
Ruby supports two main range types:
- Inclusive range:
1..5(includes 5) - Exclusive range:
1...5(excludes 5)
1) Creating Ruby Ranges
Numeric ranges
inclusive = 1..5
exclusive = 1...5
p inclusive.to_a # => [1, 2, 3, 4, 5]
p exclusive.to_a # => [1, 2, 3, 4]
Character ranges
letters = "a".."f"
p letters.to_a
# => ["a", "b", "c", "d", "e", "f"]
2) Checking if a Value is in a Range
include?
range = 10..20
puts range.include?(15) # true
puts range.include?(25) # false
cover? (often faster, doesn’t enumerate)
range = 10..20
puts range.cover?(15) # true
puts range.cover?(20) # true
Tip: cover? checks boundaries, while include? may iterate (especially for non-numeric ranges).
3) Iterating Over a Range
Using each
(1..5).each do |n|
puts n
end
Using step
(0..10).step(2) do |n|
puts n
end
# 0, 2, 4, 6, 8, 10
Using upto / downto (related, but not ranges)
1.upto(3) { |n| puts n }
3.downto(1) { |n| puts n }
4) Common Range Methods
begin, end, exclude_end?
r = 1...5
puts r.begin # 1
puts r.end # 5
puts r.exclude_end? # true
first and last
r = 1..10
puts r.first # 1
puts r.last # 10
With counts:
p (1..10).first(3) # => [1, 2, 3]
p (1..10).last(3) # => [8, 9, 10]
5) Ranges in Array Slicing
Ranges are super common when working with arrays and strings.
Array slice with a range
arr = %w[a b c d e f]
p arr[1..3] # => ["b", "c", "d"]
p arr[1...3] # => ["b", "c"]
String slice with a range
str = "Hello Ruby"
puts str[0..4] # "Hello"
puts str[6..9] # "Ruby"
6) Ranges in case Statements
Ranges are perfect for classification logic.
score = 82
grade = case score
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
when 60..69 then "D"
else "F"
end
puts grade
# => "B"
7) Ranges With Dates
Ranges also work with Date (requires date).
require "date"
week = Date.new(2025, 12, 1)..Date.new(2025, 12, 7)
puts week.cover?(Date.new(2025, 12, 3)) # true
week.each do |d|
puts d
end
8) Converting Ranges to Arrays (and When Not To)
to_a is convenient but can be expensive
p (1..10).to_a
Be careful:
# Don’t do this for huge ranges
# (1..1_000_000_000).to_a
Instead, iterate:
(1..1_000_000_000).each do |n|
break if n > 5
puts n
end
9) Filtering With Ranges
Use ranges as filters in select, grep, etc.
nums = [3, 8, 12, 19, 25, 40]
p nums.select { |n| (10..20).cover?(n) }
# => [12, 19]
Using grep:
p nums.grep(10..20)
# => [12, 19]
10) Practical Examples
Example: Paginate results (index window)
items = (1..100).to_a
page = 3
per_page = 10
start_index = (page - 1) * per_page
window = start_index...(start_index + per_page)
p items[window]
# => [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
Example: Clamp a value into bounds
range = 0..100
value = 130
clamped = [[value, range.begin].max, range.end].min
puts clamped
# => 100
FAQ (for Rich Results)
Q: What is the difference between .. and ... in Ruby ranges? A: .. includes the end value, while ... excludes the end value.
Q: How do I check if a number is inside a Ruby range? A: Use cover? or include?, for example (1..10).cover?(5).
Q: Can Ruby ranges work with strings and dates? A: Yes. Ruby ranges can represent sequences of characters and Date objects.
If you want, I can also create a Ranges cheat sheet (printable) or add practice exercises + answers for this topic.
