Question
Rails update_attributes Without Saving: How to Assign Multiple Attributes First
Question
In Rails, is there an alternative to update_attributes that updates multiple fields without immediately saving the record?
For example, I want to do something like this:
@car = Car.new(make: 'GMC')
# other processing
@car.update_attributes(model: 'Sierra', year: '2012', looks: 'Super Sexy, wanna make love to it')
# other processing
@car.save
I know I can assign each field individually, such as:
@car.model = 'Sierra'
But I want to update several attributes in a single line and save the record later.
Short Answer
By the end of this page, you will understand how to set multiple Active Record attributes in Rails without saving immediately. You will learn when to use assign_attributes, how it differs from update/update_attributes, and how this pattern is used in real Rails applications before a final save or save!.
Concept
In Rails, some Active Record methods change attributes and save right away, while others only change the object in memory.
This distinction matters because there are many situations where you want to:
- prepare an object gradually
- run extra logic before saving
- validate later
- combine changes from multiple sources
- avoid writing to the database too early
The method update_attributes was commonly used in older Rails versions to update fields and save immediately. In modern Rails, update is the preferred name, but the behavior is the same: it assigns attributes and then attempts to save the record.
If you want to assign several attributes at once without saving yet, use:
assign_attributes
This updates the model instance in memory only. The database is not touched until you call save or save!.
Example:
car = Car.new(make: 'GMC')
car.assign_attributes(model: 'Sierra', year: '2012')
# not saved yet
car.save
Why this matters in real programming:
- You may need to build an object in stages.
Mental Model
Think of an Active Record object like a paper form on your desk.
assign_attributesmeans fill in several fields on the form, but do not submit it yet.savemeans submit the form to the database.updatemeans fill in the fields and submit immediately.
So if you are still reviewing the form, adding more information, or checking for mistakes, assign_attributes is the right tool.
Syntax and Examples
The core syntax is:
record.assign_attributes(attribute_name: value, another_attribute: value)
Then save later:
record.save
Example 1: Basic usage
car = Car.new(make: 'GMC')
car.assign_attributes(model: 'Sierra', year: '2012', color: 'Black')
puts car.model
# => "Sierra"
puts car.persisted?
# => false
car.save
Explanation:
Car.new(make: 'GMC')creates a new object in memory.assign_attributes(...)sets multiple fields at once.- The record is still not saved after assignment.
savewrites it to the database.
Example 2: Existing record
car = Car.find(1)
car.assign_attributes(model: 'Sierra', year: )
car.save
Step by Step Execution
Consider this example:
car = Car.new(make: 'GMC')
car.assign_attributes(model: 'Sierra', year: '2012')
car.year = '2013'
car.save
Step by step:
-
car = Car.new(make: 'GMC')- A new
Carobject is created in memory. makeis set to"GMC".- Nothing is saved to the database yet.
- A new
-
car.assign_attributes(model: 'Sierra', year: '2012')modelbecomes"Sierra".yearbecomes"2012".- The database is still untouched.
-
car.year = '2013'- The in-memory value of
yearchanges from to .
- The in-memory value of
Real World Use Cases
Here are common cases where assigning attributes without saving is useful:
Multi-step form flow
A user fills out part of a form first, then additional details later.
@car.assign_attributes(step_one_params)
@car.assign_attributes(step_two_params)
@car.save
Data normalization before save
You receive user input, then clean it up before persisting it.
@car.assign_attributes(car_params)
@car.model = @car.model.strip.titleize
@car.save
Applying defaults or business rules
@car.assign_attributes(car_params)
@car.year ||= Time.current.year
@car.save
Combining values from different sources
For example, some values come from the form and others from an external API.
@car.assign_attributes(car_params)
@car.assign_attributes(vin_data)
@car.save
Validate before final persistence
Real Codebase Usage
In real Rails projects, developers often use this pattern when they want clearer control over when saving happens.
Pattern: build, enrich, save
car = Car.new
car.assign_attributes(car_params)
car.user = current_user
car.slug = car.model.parameterize
car.save
This is common when some attributes come from the request and others come from application logic.
Pattern: guard clauses before saving
car.assign_attributes(car_params)
return false unless car.valid?
return false unless policy(car).update?
car.save
The object is prepared first, then saved only if all checks pass.
Pattern: service objects
class UpdateCarProfile
def initialize(car, attrs)
@car = car
@attrs = attrs
end
def call
@car.assign_attributes(@attrs)
@car.last_reviewed_at = Time.current
@car.save
end
end
Common Mistakes
Mistake 1: Using update when you do not want to save yet
Broken example:
car.update(model: 'Sierra', year: '2012')
# This already attempted to save
Why it is a problem:
- The database may be updated earlier than intended.
- Validations run immediately.
- Callbacks may run immediately.
Use this instead:
car.assign_attributes(model: 'Sierra', year: '2012')
Mistake 2: Forgetting to call save
car.assign_attributes(model: 'Sierra')
# no save
If the object is never saved, the database will not change.
Mistake 3: Assuming in-memory changes are already persisted
car.assign_attributes(model: 'Sierra')
puts car.model
# => "Sierra"
Seeing the new value in Ruby does not mean it is stored in the database yet.
Comparisons
| Method | Assigns attributes? | Saves immediately? | Raises on failure? | Typical use |
|---|---|---|---|---|
assign_attributes | Yes | No | No | Prepare changes before saving |
attributes= | Yes | No | No | Older or alternative assignment syntax |
update | Yes | Yes | No | Change and save in one step |
update! | Yes | Yes | Yes | Change and save, fail loudly |
Cheat Sheet
# Assign many attributes without saving
car.assign_attributes(model: 'Sierra', year: '2012')
# Save later
car.save
# Save later and raise on failure
car.save!
# Assign and save immediately
car.update(model: 'Sierra', year: '2012')
# Assign and save immediately, raising on failure
car.update!(model: 'Sierra', year: '2012')
# Older alternative assignment syntax
car.attributes = { model: 'Sierra', year: '2012' }
Quick rules:
assign_attributeschanges the Ruby object only.savewrites pending changes to the database.updateassigns and saves in one step.update_attributesis older naming;updateis preferred in modern Rails.- Use strong parameters in controllers.
- Use
save!orupdate!when you want exceptions on failure.
FAQ
What is the Rails method to update attributes without saving?
Use assign_attributes. It sets multiple fields on the model instance without persisting them until you call save.
Does update_attributes save the record in Rails?
Yes. update_attributes assigns the values and immediately attempts to save the record. In newer Rails versions, update is the preferred method name.
What is the difference between assign_attributes and update in Rails?
assign_attributes only changes the object in memory. update changes the object and saves it to the database right away.
Can I use attributes= instead of assign_attributes?
Yes. attributes= also assigns multiple attributes without saving. However, assign_attributes is often clearer to read.
Will validations run when I call assign_attributes?
No, not by themselves. Validations normally run when you call , , , or .
Mini Project
Description
Build a small Rails-style example that prepares a Car object in stages before saving it. This demonstrates how to assign multiple attributes on one line, apply extra logic, and then persist the final version only once.
Goal
Create and modify a Car record using assign_attributes, then save it after additional processing.
Requirements
- Create a new
Carobject with an initial attribute. - Assign multiple additional attributes in one line without saving immediately.
- Modify at least one attribute again before saving.
- Check whether the object has unsaved changes.
- Save the object at the end.
Keep learning
Related questions
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.
Convert a Unix Timestamp to Ruby DateTime
Learn how to convert Unix timestamps to Ruby DateTime and Time objects, with examples, differences, pitfalls, and practical Ruby usage.