Question
I need to read data from a database and then save it to a text file.
How can I do this in Ruby? Does Ruby provide built-in file handling features for creating and writing files?
Short Answer
By the end of this page, you will understand how Ruby writes data to files, which file modes to use, how to save text safely, and how this applies to exporting database data into a text file.
Concept
Ruby has built-in file handling through the File class and related IO methods. You do not need a separate file management system just to create, read, or write files.
When you export data from a database into a text file, the process usually looks like this:
- Fetch rows from the database
- Convert each row into text
- Open a file in the correct mode
- Write the text
- Close the file
Ruby makes this simple with methods like:
File.openFile.writeputsprintwrite
The most common beginner-friendly pattern is a block with File.open, because Ruby automatically closes the file when the block ends.
File.open("output.txt", "w") do |file|
file.puts "Hello, world!"
end
This matters in real programming because many applications need to:
- export reports
- generate logs
- save backups
- create CSV or text files
- write API results to disk
Using the correct file mode is important:
"w"creates or overwrites a file"a"appends to the end of a file"r"reads from a file
For database exports, you will often loop through query results and write one line per record.
Mental Model
Think of a file as a notebook on your desk.
- Opening a file is like opening the notebook.
- Writing to it is like adding lines with a pen.
- Closing it is like shutting the notebook so nothing is left unfinished.
Ruby's block form of File.open is like asking someone to open the notebook, let you write in it, and then automatically close it when you are done. That is why it is safer and more convenient than opening and closing manually.
Syntax and Examples
Basic file writing
File.open("notes.txt", "w") do |file|
file.puts "First line"
file.puts "Second line"
end
What this does
- Opens
notes.txtin write mode - Creates the file if it does not exist
- Overwrites the file if it already exists
- Writes two lines
- Closes the file automatically
Quick one-line write
File.write("notes.txt", "Hello from Ruby\n")
This is useful when you already have all content in one string.
Append instead of overwrite
File.open("notes.txt", "a") do |file|
file.puts "Another line"
end
This adds content to the end of the file instead of replacing it.
Example: save database-style records
users = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }
]
File.open("users.txt", "w") do |file|
users.each do |user|
file.puts "#{user[:id]}, #{user[:name]}, #{user[:email]}"
end
end
Explanation
userssimulates rows returned from a databaseeachloops through every recordfile.putswrites one formatted line per user
The resulting file would look like:
1, Alice, alice@example.com
2, Bob, bob@example.com
Step by Step Execution
products = ["Book", "Pen", "Laptop"]
File.open("products.txt", "w") do |file|
products.each do |product|
file.puts product
end
end
Step by step
- Ruby creates an array named
products. File.open("products.txt", "w")opens the file in write mode.- If the file does not exist, Ruby creates it.
- If it exists, Ruby clears the old contents.
- The opened file object is passed into the block as
file. products.eachstarts looping through the array.- First iteration:
productis"Book"file.puts productwritesBookand a newline
- Second iteration:
productis"Pen"- Ruby writes
Pen
- Third iteration:
productis"Laptop"- Ruby writes
Laptop
- The block ends.
- Ruby automatically closes the file.
Final file content:
Book
Pen
Laptop
Real World Use Cases
Ruby file writing is commonly used for:
- Database exports: save query results into
.txt,.csv, or log files - Report generation: create daily summaries or audit reports
- Logging: store errors, warnings, or job output
- Backups: save data snapshots before updates
- Data exchange: write files to be consumed by another system
- Scripts and automation: store processed results from scraping, APIs, or batch jobs
Example: exporting customer names from a database query result
customers = ["Anna", "David", "Maria"]
File.open("customers.txt", "w") do |file|
customers.each do |name|
file.puts name
end
end
In a Rails app, this same idea is often used when generating exports in background jobs or admin tools.
Real Codebase Usage
In real projects, developers rarely just write raw text without structure. They usually combine file writing with patterns like validation, formatting, and error handling.
Common patterns
Guard clause before writing
records = []
return if records.empty?
This avoids creating an empty export unnecessarily.
Build lines before saving
lines = ["Header"]
lines << "Row 1"
lines << "Row 2"
File.write("report.txt", lines.join("\n") + "\n")
This is useful when the full content is easy to build in memory first.
Write inside an iteration for large datasets
File.open("report.txt", "w") do |file|
records.each do |record|
file.puts record.to_s
end
end
This is often better when many rows are involved, because you do not need to keep the entire file content in one string.
Error handling
begin
File.open("report.txt", "w") do |file|
file.puts "Export started"
end
rescue Errno::EACCES
puts "Permission denied"
rescue Errno::ENOENT
puts "Directory does not exist"
end
This is important in production code because file paths, permissions, and disk issues can fail.
Formatting database rows
File.open("users.txt", "w") do |file|
users.each do |user|
next if user[:email].nil?
file.puts "#{user[:name]} <#{user[:email]}>"
end
end
This shows validation and filtering before writing.
Common Mistakes
1. Using write mode when you meant append mode
Broken example:
File.open("log.txt", "w") do |file|
file.puts "New log entry"
end
Problem:
"w"deletes existing content before writing.
Fix:
File.open("log.txt", "a") do |file|
file.puts "New log entry"
end
2. Forgetting that write does not add a newline
Broken example:
File.open("names.txt", "w") do |file|
file.write "Alice"
file.write "Bob"
end
Result:
AliceBob
Fix:
File.open("names.txt", "w") do |file|
file.puts "Alice"
file.puts "Bob"
end
3. Opening a file without closing it manually
Less safe approach:
file = File.open("data.txt", "w")
file.puts "Hello"
Problem:
- The file may stay open longer than intended.
Fix:
File.open("data.txt", "w") do |file|
file.puts "Hello"
end
4. Writing to a path that does not exist
Broken example:
File.write("exports/users/data.txt", "test")
Problem:
- Ruby raises an error if the directory does not exist.
Fix:
Dir.mkdir("exports") unless Dir.exist?("exports")
Dir.mkdir("exports/users") unless Dir.exist?("exports/users")
File.write("exports/users/data.txt", "test")
5. Assuming database objects can always be written directly
Broken example:
file.puts user
Problem:
- The default object output may not be useful.
Fix:
file.puts "#{user[:id]}, #{user[:name]}, #{user[:email]}"
Always format the data into meaningful text first.
Comparisons
| Approach | Best for | Overwrites? | Adds newline automatically? | Notes |
|---|---|---|---|---|
| `File.open("file.txt", "w") { | f | f.puts ... }` | General writing | Yes |
| `File.open("file.txt", "a") { | f | f.puts ... }` | Logs and appending | No |
File.write("file.txt", content) | Writing one full string | Yes | No | Simple and concise |
file.write(content) | Exact text output | Depends on mode | No | Good when you want full control |
file.puts(content) | Writing lines | Depends on mode | Yes | Beginner-friendly |
puts vs write
| Method | Adds newline | Good for |
|---|---|---|
puts | Yes | Writing line-by-line text |
write | No | Writing exact content without automatic formatting |
w vs a
| Mode | Meaning | Use when |
|---|---|---|
w | Write | You want a fresh file each time |
a | Append | You want to keep old content and add more |
Cheat Sheet
File writing basics in Ruby
File.open("file.txt", "w") do |file|
file.puts "Hello"
end
Common file modes
"r"= read"w"= write and overwrite"a"= append
Common methods
File.open(path, mode)— open a fileFile.write(path, content)— write a whole string at oncefile.puts(text)— write text with newlinefile.write(text)— write text exactly as given
Safe pattern
File.open("data.txt", "w") do |file|
file.puts "line 1"
end
Append example
File.open("data.txt", "a") do |file|
file.puts "new line"
end
Export array to file
items = ["A", "B", "C"]
File.open("items.txt", "w") do |file|
items.each { |item| file.puts item }
end
Important rules
"w"erases old content"a"keeps old contentputsadds a newlinewritedoes not add a newline- Block form of
File.opencloses the file automatically
Common errors
- Writing to a missing directory
- Using
"w"when you wanted"a" - Forgetting to format database rows into readable text
FAQ
How do I create a text file in Ruby?
Use File.open with write mode:
File.open("example.txt", "w") { |file| file.puts "Hello" }
If the file does not exist, Ruby creates it.
How do I append text to an existing file in Ruby?
Use append mode:
File.open("example.txt", "a") { |file| file.puts "More text" }
Does Ruby have built-in file handling?
Yes. Ruby includes built-in classes such as File and IO for reading, writing, and managing files.
What is the difference between puts and write in Ruby files?
puts adds a newline automatically. write writes the exact string as-is.
Can I export database records to a text file in Ruby?
Yes. Query the records, loop through them, format each row as text, and write each line to a file.
What happens if the file already exists?
With "w", the file is overwritten. With "a", new content is added to the end.
What is the safest way to write files in Ruby?
Use the block form of File.open, because Ruby closes the file automatically when the block ends.
Mini Project
Description
Create a simple Ruby export script that takes a list of users and saves them into a text file. This demonstrates the same core idea used when exporting database query results in real applications.
Goal
Write a Ruby script that saves multiple user records into a text file, one user per line.
Requirements
- Create an array of user records using hashes
- Open a text file in write mode
- Write one formatted line per user
- Close the file safely using the block form of
File.open - Print a success message after the export finishes
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.