rubyguides

String#end_with?

str.end_with?(*suffixes) -> true or false

The end_with? method checks whether a string ends with one or more specified suffixes. It returns true if the string ends with any of the given substrings, otherwise false. This method is case-sensitive.

Syntax

str.end_with?(*suffixes)

Parameters

ParameterTypeDefaultDescription
*suffixesStringOne or more substrings to check as potential endings

Examples

The examples below show the most common suffix-checking patterns, starting with the simplest case and building toward practical validation helpers.

Basic usage

"hello".end_with?("o")
# => true

"hello".end_with?("lo")
# => true

"hello".end_with?("ll")
# => false

These short checks show the core rule clearly: the ending either matches or it does not. That makes the method a good fit for situations where the suffix itself carries the meaning, such as a file extension or a known route ending. The method reads naturally in an if statement because the question mark in the method name signals a boolean check.

Checking multiple suffixes

"document.txt".end_with?(".txt", ".pdf", ".doc")
# => true

"image.png".end_with?(".txt", ".pdf")
# => false

Passing several suffixes keeps the policy in one place. If the app accepts more than one ending, the method can test them in a single call instead of repeating the same condition over and over. This is especially helpful in validation code where the list of accepted suffixes may grow over time and keeping them together makes the policy easier to audit.

Case sensitivity

"Ruby".end_with?("ruby")
# => false

"Ruby".end_with?("Ruby")
# => true

Case-sensitive matching is usually what you want when the exact ending matters. If the input comes from a user or another system, normalize the case first so the suffix check stays simple. Normalizing before checking is especially important when the input source is not under your control, such as user-submitted filenames or data from an external API.

Common Patterns

File extension checking

def text_file?(filename)
  filename.end_with?(".txt", ".md", ".rtf")
end

text_file?("readme.md")      # => true
text_file?("script.rb")      # => false

This style reads well because the whitelist of accepted endings is visible right in the method call. A reader can tell at a glance which file types are allowed without digging through another helper. The method name itself acts as documentation, since text_file? makes the intent clear before you even read the arguments.

URL path validation

def html_page?(path)
  path.end_with?(".html", ".htm")
end

html_page?("/about.html")   # => true
html_page?("/about")        # => false

The same pattern works for URL paths, where the suffix often maps directly to a route or document type. Keeping the rule local to the check makes the validation easy to update later.

Use end_with? for suffix checks

end_with? is the method you reach for when the end of a string carries the rule you need to test. File names, URL paths, and tagged values all fit that shape well. The call reads clearly because the suffix is right there in the argument list, so the code tells you exactly what ending it expects. That makes the method easy to scan in validation code, where you often care more about the ending than the rest of the string.

Check several endings at once

The method accepts more than one suffix, which is handy when several endings should be treated the same way. A file picker might accept .txt, .md, or .rtf, and a route guard might accept more than one path form. Putting the choices in one call keeps the rule visible and avoids a chain of repeated checks. That can make the code easier to read than a longer boolean expression built from separate comparisons.

Keep the condition close to the domain

end_with? works best when the suffix list reflects the domain language of the app. If the code is checking a file extension, a protocol marker, or a resource name, the string literal should make that shape obvious. A reader should not have to guess why the ending matters. When the condition stays close to the thing it is validating, the method becomes a clear, tiny rule instead of a hidden assumption buried in the line.

That clarity is the main reason to prefer a suffix check over a broader string search. The rule is narrower, easier to explain, and less likely to accidentally match something in the middle of the value.

Checking case-insensitive suffixes

end_with? is case-sensitive, so if you need a case-insensitive suffix check, normalize the string first:

filename = "README.MD"
filename.downcase.end_with?(".md")  # => true
"/ABOUT.HTML".downcase.end_with?(".html")  # => true

This pattern keeps the suffix check simple while handling mixed-case inputs from users or external systems. The normalization step is explicit, so readers can see where the case folding happens without tracing through a helper method.

Chaining with other string methods

end_with? pairs well with other string checks in guard clauses and validation pipelines. The return value is a simple boolean, so it chains naturally in conditional expressions:

filename = "report.pdf"
if filename.end_with?(".pdf") && File.exist?(filename)
  puts "Found: #{filename}"
end

# Or with inline rescue for quick validation
valid = path.end_with?("/") rescue false

Because end_with? never raises on its own, the inline rescue here only catches issues from a nil receiver. That pattern is compact enough for one-liners but explicit enough to show the reader exactly what the code expects.

See Also