Build::Files::MonitorGuidesGetting Started

Getting Started

This guide explains how to use build-files-monitor to efficiently monitor the filesystem for changes.

Installation

Add the gem to your project:

$ bundle add build-files-monitor

Core Concepts

build-files-monitor provides efficient filesystem monitoring using platform-specific native APIs:

Usage

Basic File Monitoring

Here's a simple example that monitors a directory for changes:

require "build/files/path"
require "build/files/directory"
require "build/files/monitor"

# Create a path to monitor:
root = Build::Files::Path.current

# Monitor everything within this directory, recursively:
directory = Build::Files::Directory.new(root)

# Create a monitor instance (uses native platform APIs):
monitor = Build::Files::Monitor.new

# Track changes with a callback:
monitor.track_changes(directory) do |state|
	puts "Files added: #{state.added.inspect}"
	puts "Files changed: #{state.changed.inspect}"
	puts "Files removed: #{state.removed.inspect}"
end

# Run the monitor (blocking):
monitor.run

Detecting Specific Changes

The state object passed to your callback provides detailed information about what changed:

monitor.track_changes(directory) do |state|
	# Check for specific types of changes:
	unless state.added.empty?
		puts "New files detected:"
		state.added.each do |path|
			puts "  + #{path}"
		end
	end
	
	unless state.changed.empty?
		puts "Modified files:"
		state.changed.each do |path|
			puts "  ~ #{path}"
		end
	end
	
	unless state.removed.empty?
		puts "Deleted files:"
		state.removed.each do |path|
			puts "  - #{path}"
		end
	end
end

Running with Custom Latency

You can control how often the monitor checks for changes:

# Check for changes every 2 seconds (default is 0.1 seconds):
monitor.run(latency: 2.0) do
	# Optional block that runs after each check:
	puts "Checked at #{Time.now}"
end

Stopping the Monitor

Use throw :interrupt to stop the monitor from within your callback or the run block:

changes_detected = 0

monitor.track_changes(directory) do |state|
	changes_detected += 1
	
	# Stop after detecting 5 changes:
	if changes_detected >= 5
		puts "Detected 5 changes, stopping monitor"
		throw :interrupt
	end
end

monitor.run
puts "Monitoring stopped"

Monitoring Multiple Directories

You can track changes in multiple directories simultaneously:

monitor = Build::Files::Monitor.new

# Track the first directory:
dir1 = Build::Files::Directory.new(Build::Files::Path.expand("src"))
monitor.track_changes(dir1) do |state|
	puts "Changes in src/: #{state.added.size + state.changed.size}"
end

# Track a second directory:
dir2 = Build::Files::Directory.new(Build::Files::Path.expand("config"))
monitor.track_changes(dir2) do |state|
	puts "Changes in config/: #{state.added.size + state.changed.size}"
end

# Run the monitor for both:
monitor.run

Removing Tracked Directories

You can stop monitoring a directory by calling remove! on the handle:

handle = monitor.track_changes(directory) do |state|
	puts "Change detected!"
end

# Later, stop monitoring this directory:
handle.remove!

Using Specific Implementations

By default, Build::Files::Monitor.new creates a Native monitor. You can also directly instantiate specific implementations:

# Use native monitoring (default):
monitor = Build::Files::Monitor::Native.new

# Or use polling mode (useful for testing or special scenarios):
monitor = Build::Files::Monitor::Polling.new