Ruby
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Methods and Blocks
-
Section 4: Object-Oriented Ruby
-
Section 5: Metaprogramming
-
Section 6: Working with Data and Files
-
Section 7: Ruby Frameworks Overview
-
Section 8: Ecosystem and Testing
-
Section 9: Practical Projects
-
Section 10: Interview Practice
-
Section 11: Data Structures and Algorithms in Ruby
-
Section 12: More Practice Exercises
-
Section 13: Enumerable and Functional Style
-
Section 14: More OOP Practice
-
Section 15: More Testing
-
Section 16: Enumerable and Comparable Modules In Depth
-
Section 17: Ruby Standard Library: Core Utilities
-
Section 18: Ruby Standard Library: Data and Security
-
Section 19: Ruby Standard Library: CLI and Text
-
Section 20: Ruby Networking
-
Section 21: Ruby on Rails Deep Dive
-
Section 22: Ruby Metaprogramming Deep Dive
-
Section 23: Ruby Design Patterns
-
Section 24: Ruby Concurrency
-
Section 25: Ruby Testing Deep Dive
-
Section 26: Ruby Gems and Packaging
-
Section 27: Ruby Performance
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Rails API Development
-
Section 31: Rails Authentication and Authorization
-
Section 32: Rails Testing Deep Dive
-
Section 33: Rails Performance
-
Section 34: Rails Deployment
-
Section 35: Sinatra and Lightweight Ruby Web Apps
-
Section 36: More Ruby Language Deep Dive
-
Section 37: Ruby 3.x Modern Features
-
Section 38: More Data Structures in Ruby
-
Section 39: More Practical Projects
-
Section 40: Ruby Ecosystem Tools
-
Section 41: More Practice and Review
-
Section 42: Final Practice and Mastery
-
Section 43: Ruby Interview Deep Dive
-
Section 44: Ruby Background Processing Deep Dive
-
Section 45: Ruby GraphQL
-
Section 46: Ruby Object Model Deep Dive
-
Section 47: Ruby Hanami Framework Overview
-
Section 48: Ruby gRPC and Protocol Buffers
-
Section 49: Ruby Data Processing
-
Section 50: Ruby Search Integration
-
Section 51: Ruby File Upload and Media
-
Section 52: Ruby Email and Notifications
-
Section 53: Ruby Admin Panels
-
Section 54: Ruby Feature Flags and Experimentation
-
Section 55: Ruby Monitoring and Observability
-
Section 56: Ruby Docker and Deployment Deep Dive
-
Section 57: Ruby Security Deep Dive
-
Section 58: More Advanced Metaprogramming
-
Section 59: More Final Projects
66: FileUtils for File Operations
I see this all the time when I'm reviewing code from developers moving into Ruby: they treat the File class as the one-stop shop for every single interaction with the disk. They assume that because it's called File, it must handle every "file-related" task you could possibly imagine.
The "File Class Does Everything" Myth
Here is the reality: the File class is great for reading, writing, and checking the properties of a single file. But the moment you try to do "system-level" operations—like moving a directory or deleting a folder that isn't empty—File will let you down. Look at this example:
# Let's say we have a folder called 'old_logs' with 50 files inside it.
File.delete('old_logs')
# Result: Errno::EISDIR (Is a directory)
Ruby is telling you, "Hey, this is a directory, not a file!" To get around this using only the File class, you'd have to write a recursive loop to find every file, delete them individually, and then finally delete the directory. That's a waste of your time. I don't want you writing boilerplate when the standard library already solved this for us.
Moving to FileUtils for Shell-Like Power
This is where FileUtils comes in. Think of FileUtils not as a way to handle file content, but as a way to perform shell commands (like cp, mv, and rm -rf) directly within your Ruby code. You'll need to require 'fileutils' because, unlike the File class, it isn't loaded by default.
One of the most useful methods you'll use is mkdir_p. The 'p' stands for parents. If you try to create /backups/2023/october but none of those folders exist yet, a standard Dir.mkdir will crash. FileUtils.mkdir_p just makes it happen, creating every missing folder in the chain.
require 'fileutils'
# No matter how deep the path is, this just works.
FileUtils.mkdir_p('archives/logs/daily')
Handling Bulk Moves and Recursive Copies
When you're managing a project's assets or logs, you rarely move one file. You usually move groups. FileUtils.mv is your friend here. It handles both files and directories seamlessly. If you need to copy an entire directory structure—say, duplicating a template folder for a new user—use cp_r (the 'r' is for recursive).
# Copying a configuration template directory to a user's specific folder
FileUtils.cp_r('config/templates/default', 'config/users/user_42')
# Moving a finished export to the archives
FileUtils.mv('exports/report_final.csv', 'archives/2023/report_final.csv')
The Nuclear Option: rm_rf
Between us, FileUtils.rm_rf is the most dangerous method in this module. It's the Ruby equivalent of rm -rf /. It deletes a file or a directory (and everything inside it) without asking for permission and without raising an error if the path doesn't even exist.
I use it frequently for cleaning up temporary build directories, but please, be incredibly careful with the variables you pass into it. One misplaced string and you could wipe out your entire project directory.
# Cleaning up a temporary directory before a new build
FileUtils.rm_rf('tmp/cache')
📋 Practical Task
Exercise: Automated Log Rotation and Archiving Script
You need to build a script that cleans up a messy logs/ directory. Your script should perform the following sequence of operations:
- Create a directory path
archives/logs/backup_currentusingmkdir_pto ensure the full path exists. - Assume there are several files in the
logs/folder (you can create a few dummy files likelog1.txt,log2.txt). - Move all files ending in
.txtfrom thelogs/folder into thearchives/logs/backup_currentfolder. - Finally, delete the original
logs/directory and all its remaining contents using the "nuclear" method.
Requirement: Your solution must use FileUtils for the directory creation, the moving, and the final deletion.
There are no comments for now.