Question

Rails update_attributes Without Saving: How to Assign Multiple Attributes First

rubyruby-on-railsruby-on-rails-3ruby-on-rails-4rails-activerecord

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.
  • You may want to inspect or modify data before saving.
  • You may want a single save operation after multiple changes.
  • You may want validations to run only once at the end.

So the key idea is:

  • assign_attributes = set many attributes now, save later
  • update / update_attributes = set many attributes and save immediately

Mental Model

Think of an Active Record object like a paper form on your desk.

  • assign_attributes means fill in several fields on the form, but do not submit it yet.
  • save means submit the form to the database.
  • update means 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.

Take Quiz

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.
  • save writes it to the database.

Example 2: Existing record

car = Car.find(1)
car.assign_attributes(model: 'Sierra', year: '2012')
# database still unchanged here
car.save

This also works for an existing record. Rails marks the changed fields as dirty, but does not persist them until save.

Example 3: Compare with update

car = Car.find(1)
car.update(model: 'Sierra', year: '2012')

This assigns the values and immediately attempts to save.

Older alias

In older Rails code, you may see:

car.attributes = { model: 'Sierra', year: '2012' }

This also assigns attributes without saving. In many codebases, assign_attributes is clearer and more explicit.

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:

  1. car = Car.new(make: 'GMC')

    • A new Car object is created in memory.
    • make is set to "GMC".
    • Nothing is saved to the database yet.
  2. car.assign_attributes(model: 'Sierra', year: '2012')

    • model becomes "Sierra".
    • year becomes "2012".
    • The database is still untouched.
  3. car.year = '2013'

    • The in-memory value of year changes from "2012" to "2013".
    • Still not saved yet.
  4. car.save

    • Rails runs validations.
    • If valid, Rails inserts or updates the database row.
    • The saved value for year will be "2013".

The important lesson is that all assignments made before save are just preparing the object. Only save persists them.

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

@car.assign_attributes(car_params)
if @car.valid?
  # do more work
  @car.save
end
Take Quiz

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

This keeps business logic organized and avoids accidental early database writes.

Pattern: error handling with save!

car.assign_attributes(car_params)
car.save!

Use save! when you want Rails to raise an exception if saving fails.

Pattern: transactional workflows

Car.transaction do
  car.assign_attributes(car_params)
  car.save!
  AuditLog.create!(action: 'car_updated', record: car)
end

This is useful when saving the model is only one part of a larger operation.

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.

Mistake 4: Confusing save and save!

car.save
  • save returns true or false
  • save! raises an exception on failure

If you need failure to be loud and explicit, use save!.

Mistake 5: Using deprecated style without knowing your Rails version

Older tutorials may use update_attributes. In newer Rails versions, update is preferred.

Mistake 6: Passing untrusted params directly

In controllers, use strong parameters.

@car.assign_attributes(params[:car])

Avoid doing this directly. Prefer:

@car.assign_attributes(car_params)

Comparisons

MethodAssigns attributes?Saves immediately?Raises on failure?Typical use
assign_attributesYesNoNoPrepare changes before saving
attributes=YesNoNoOlder or alternative assignment syntax
updateYesYesNoChange and save in one step
update!YesYesYesChange and save, fail loudly
saveNoYesNoPersist current in-memory changes
save!NoYesYesPersist current changes, fail loudly

assign_attributes vs individual setters

car.model = 'Sierra'
car.year = '2012'

vs

car.assign_attributes(model: 'Sierra', year: '2012')

Both are valid. assign_attributes is cleaner when updating many fields together.

assign_attributes vs update

  • Use assign_attributes when you want to save later.
  • Use update when you want a single operation that assigns and persists immediately.
Take Quiz

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_attributes changes the Ruby object only.
  • save writes pending changes to the database.
  • update assigns and saves in one step.
  • update_attributes is older naming; update is preferred in modern Rails.
  • Use strong parameters in controllers.
  • Use save! or update! when you want exceptions on failure.

Useful check:

car.changed?

This tells you whether the model has unsaved changes.

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 save, save!, update, or valid?.

How do I know whether the record has unsaved changes?

Use Rails dirty tracking methods such as:

car.changed?

This returns whether any attributes were modified but not yet saved.

Should I use save or save! after assign_attributes?

Use save if you want a true/false result. Use save! if you want an exception raised when the record is invalid or saving fails.

Take Quiz

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 Car object 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.
Take Quiz

Keep learning

Related questions

View more