# derive-builder-apply-to
A procedural macro for generating `apply_to` methods for builder patterns, designed to work seamlessly with the [`derive_builder`](https://crates.io/crates/derive_builder) crate.
## Overview
The [`derive_builder`](https://crates.io/crates/derive_builder) crate is fantastic for creating new objects using the builder pattern. However, builders are typically used only for construction - once you call `.build()`, the builder is consumed.
This crate extends that functionality by allowing you to use builders to **modify existing structs**. Instead of building new objects, you can selectively update existing ones with only the fields you want to change.
This is especially useful for:
- Partial updates in APIs (PATCH operations)
- Configuration merging
- Applying user preferences to default settings
- Any scenario where you want to modify only specific fields
The `ApplyTo` derive macro generates an `apply_to` method on builder structs that:
- Applies only the fields that have been explicitly set (non-`None` values)
- Returns a boolean indicating whether any changes were made
- Avoids unnecessary writes when values haven't changed
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
derive_builder = "0.20"
derive-builder-apply-to = "0.1.0"
```
Then derive both `Builder` and `ApplyTo` on your struct:
```rust
use derive_builder::Builder;
use derive_builder_apply_to::ApplyTo;
#[derive(Builder, ApplyTo, Default, Debug, PartialEq)]
struct Person {
name: String,
age: u32,
email: Option<String>,
}
fn main() {
// Create an existing person
let mut person = Person {
name: "Alice".to_string(),
age: 30,
email: Some("alice@example.com".to_string()),
};
// Use builder to apply updates directly - no .build() needed!
let changed = PersonBuilder::default()
.age(31)
.email(Some("alice.smith@example.com".to_string()))
.apply_to(&mut person);
assert!(changed);
assert_eq!(person.name, "Alice"); // unchanged
assert_eq!(person.age, 31); // updated
assert_eq!(person.email, Some("alice.smith@example.com".to_string())); // updated
// Applying the same values again returns false
let changed = PersonBuilder::default()
.age(31)
.apply_to(&mut person);
assert!(!changed); // No change since age was already 31
}
```
## How it works
The `ApplyTo` derive macro:
1. Inspects your struct's fields
2. Generates an `apply_to` method on the corresponding builder struct (e.g., `PersonBuilder`)
3. The method iterates through each `Option<T>` field in the builder
4. For each `Some(value)`, it compares with the target struct's field
5. Updates the target field only if the value is different
6. Returns `true` if any field was changed, `false` otherwise
## Requirements
- Your struct must work with `derive_builder` (named fields only)
- Field types must implement `PartialEq` for change detection
- The builder struct must have `Option<T>` fields for optional updates
## License
Licensed under the MIT License.