Touch

The Touch functionality in CQL Active Record allows you to update timestamp fields (like updated_at, created_at, or custom timestamp fields) without triggering any callbacks like validations, before/after save hooks, or other lifecycle callbacks.

This is particularly useful when you want to mark records as "recently accessed" or update timestamps for logging purposes without running the full save cycle.

Overview

Touch provides a lightweight way to update timestamp columns directly in the database, bypassing the entire Active Record callback chain including:

  • Validation callbacks (before_validation, after_validation)

  • Save callbacks (before_save, after_save)

  • Create/Update callbacks (before_create, after_create, before_update, after_update)

Basic Usage

Instance Methods

#touch(*fields, time: Time = Time.utc)

Updates specified timestamp fields to the current time (or a custom time) without running callbacks.

# Touch the default updated_at field
user.touch
# => Updates user.updated_at to current time

# Touch specific timestamp fields
user.touch(:last_seen_at)
# => Updates user.last_seen_at to current time

# Touch multiple fields
user.touch(:updated_at, :last_accessed_at)
# => Updates both fields to current time

# Touch with custom time
specific_time = Time.utc - 1.hour
user.touch(:updated_at, time: specific_time)
# => Updates user.updated_at to the specified time

#touch!(time: Time = Time.utc)

Convenience method that specifically touches the updated_at field.

Class Methods

.touch_all(ids, *fields, time: Time = Time.utc)

Updates timestamp fields for multiple records by their IDs without loading them into memory or running callbacks.

Examples

Basic Record Touching

Tracking User Activity

Cache Invalidation

Behavior Details

What Touch Does

  1. Updates Database Directly: Executes an UPDATE query directly against the database

  2. Updates Local Instance: Synchronizes the local object's timestamp attributes with the database

  3. Returns Success Status: Returns true if the update was successful, false otherwise

  4. No Callbacks: Completely bypasses all Active Record callbacks and validations

What Touch Doesn't Do

  1. No Validation: Does not run any model validations

  2. No Callbacks: Does not trigger any lifecycle callbacks

  3. No Dirty Tracking: Does not mark attributes as changed/dirty

  4. No Version Bumping: Does not increment optimistic locking version numbers

Error Conditions

Touch will raise errors in these situations:

Use Cases

1. Activity Tracking

Update last_seen_at timestamps when users access the application:

2. Cache Invalidation

Mark records as updated to invalidate cached data:

3. Background Job Processing

Update processing timestamps in background jobs:

4. API Rate Limiting

Track API usage without expensive model updates:

Performance Benefits

Touch is significantly more performant than regular saves because it:

  • Skips validation logic

  • Bypasses callback chains

  • Executes minimal SQL UPDATE statements

  • Doesn't instantiate full objects for batch operations

  • Avoids complex change tracking

This makes it ideal for high-frequency timestamp updates like activity tracking, cache invalidation, and background processing scenarios.

Comparison with Regular Save

Operation
Callbacks
Validations
SQL Queries
Performance

user.save!

✅ All callbacks run

✅ Full validation

Multiple (if callbacks query DB)

Slower

user.touch

❌ No callbacks

❌ No validation

Single UPDATE

Faster

User.touch_all(ids)

❌ No callbacks

❌ No validation

Single UPDATE with IN clause

Fastest

Best Practices

  1. Use for Timestamp Updates: Touch is designed specifically for timestamp fields

  2. Prefer Batch Operations: Use touch_all for updating multiple records efficiently

  3. Avoid for Business Logic: Don't use touch when you need validations or callbacks

  4. Consider Cache Impact: Remember that touching may affect timestamp-based caching

  5. Monitor Performance: Touch is fast, but avoid excessive database updates in tight loops

Integration with Existing Code

Touch integrates seamlessly with existing Active Record models. Simply add timestamp properties to your models and start using the touch methods:

The touch functionality respects your existing schema and will work with any Time-typed columns in your database tables.

Last updated

Was this helpful?