---
title: "Life of save in ActiveRecord"
description:
  "ActiveRecord saves record by going through saving process in layers. This
  blog takes a deep dive into how ActiveRecord saves a record."
canonical_url: "https://www.bigbinary.com/blog/live-of-save-in-activerecord"
markdown_url: "https://www.bigbinary.com/blog/live-of-save-in-activerecord.md"
---

# Life of save in ActiveRecord

ActiveRecord saves record by going through saving process in layers. This blog
takes a deep dive into how ActiveRecord saves a record.

- Author: Neeraj Singh
- Published: January 15, 2013
- Categories: Rails

_Following code was tested with edge rails (rails4) ._

In a RubyonRails application we save records often. It is one of the most used
methods in ActiveRecord. In the blog we are going to take a look at the life
cycle of save operation.

## ActiveRecord::Base

A typical model looks like this.

```ruby
class Article < ActiveRecord::Base
end
```

Now lets look at ActiveRecord::Base class in its entirety.

```ruby
module ActiveRecord
  class Base
    extend ActiveModel::Naming

    extend ActiveSupport::Benchmarkable
    extend ActiveSupport::DescendantsTracker

    extend ConnectionHandling
    extend QueryCache::ClassMethods
    extend Querying
    extend Translation
    extend DynamicMatchers
    extend Explain

    include Persistence
    include ReadonlyAttributes
    include ModelSchema
    include Inheritance
    include Scoping
    include Sanitization
    include AttributeAssignment
    include ActiveModel::Conversion
    include Integration
    include Validations
    include CounterCache
    include Locking::Optimistic
    include Locking::Pessimistic
    include AttributeMethods
    include Callbacks
    include Timestamp
    include Associations
    include ActiveModel::SecurePassword
    include AutosaveAssociation
    include NestedAttributes
    include Aggregations
    include Transactions
    include Reflection
    include Serialization
    include Store
    include Core
  end

  ActiveSupport.run_load_hooks(:active_record, Base)
end
```

`Base` class extends and includes a lot of modules. Here we are going to look at
the four modules that have method `def save` .

```ruby
module ActiveRecord
  class Base
    ......................
    include Persistence
    .......................
    include Validations
    ........................
    include AttributeMethods
    ........................
    include Transactions
    ........................
  end
end
```

## include Persistence

Module `Persistence` defines `save` method like this

```ruby
def save(*)
  create_or_update
rescue ActiveRecord::RecordInvalid
  false
end
```

Now lets see method `create_or_update` .

```ruby
def create_or_update
  raise ReadOnlyRecord if readonly?
  result = new_record? ? create_record : update_record
  result != false
end
```

So `save` method invokes `create_or_update` and `create_or_update` method either
creates a record or updates a record. Dead simple.

## include Validations

In module `Validations` the `save` method is defined as

```ruby
def save(options={})
  perform_validations(options) ? super : false
end
```

In this case the `save` method simply invokes a call to `perform_validations` .

## include AttributeMethods

Module `AttributeMethods` includes a bunch of modules like this

```ruby
module ActiveRecord
  module AttributeMethods
    extend ActiveSupport::Concern
    include ActiveModel::AttributeMethods

    included do
      include Read
      include Write
      include BeforeTypeCast
      include Query
      include PrimaryKey
      include TimeZoneConversion
      include Dirty
      include Serialization
    end
```

Here we want to look at `Dirty` module which has `save` method defined as
following.

```ruby
def save(*)
  if status = super
    @previously_changed = changes
    @changed_attributes.clear
  end
  status
end
```

Since this module is all about tracking if a record is dirty or not, the `save`
method tracks the changed values.

## include Transactions

In module `Transactions` the `save` method is defined as

```ruby
def save(*) #:nodoc:
  rollback_active_record_state! do
    with_transaction_returning_status { super }
  end
end
```

The method `rollback_active_record_state!` is defined as

```ruby
def rollback_active_record_state!
  remember_transaction_record_state
  yield
rescue Exception
  restore_transaction_record_state
  raise
ensure
  clear_transaction_record_state
end
```

And the method `with_transaction_returning_status` is defined as

```ruby
def with_transaction_returning_status
  status = nil
  self.class.transaction do
    add_to_transaction
    begin
      status = yield
    rescue ActiveRecord::Rollback
      @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
      status = nil
    end

    raise ActiveRecord::Rollback unless status
  end
  status
end
```

Together methods `rollback_active_record_state!` and
`with_transaction_returning_status` ensure that all the operations happening
inside `save` is happening in a single transaction.

## Why save method needs to be in a transaction .

A model can define a number of callbacks including `after_save` and
`before_save`. All those callbacks are operated within a transaction. It means
if an `after_save` callback operation raises an exception then the `save`
operation is rolled back.

Not only that a number of associations like `has_many` and `belongs_to` use
callbacks to handle association manipulation. In order to ensure the integrity
of the operation the save operation is wrapped in a transaction .

## reverse order of operation

In the `Base` class the modules are included in the following order.

```ruby
module ActiveRecord
  class Base
    ......................
    include Persistence
    .......................
    include Validations
    ........................
    include AttributeMethods
    ........................
    include Transactions
    ........................
  end
end
```

All the four modules have `save` method. The way ruby works the last module to
be included gets to act of the method first. So the order in which `save` method
gets execute is `Transactions`, `AttributeMethods`, `Validations` and
`Persistence` .

To get a visual feel, I added a `puts` inside each of the save methods. Here is
the result.

```ruby
> User.new.save
1.9.1 :001 > User.new.save
entering save in transactions
   (0.1ms)  begin transaction
entering save in attribute_methods
entering save in validations
entering save in persistence
  SQL (47.3ms)  INSERT INTO "users" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", Mon, 21 Jan 2013 14:56:52 UTC +00:00], ["updated_at", Mon, 21 Jan 2013 14:56:52 UTC +00:00]]
leaving save in persistence
leaving save in validations
leaving save in attribute_methods
   (17.6ms)  rollback transaction
leaving save in transactions
 => nil
```

As you can see the order of operations is

```ruby
entering save in transactions
entering save in attribute_methods
entering save in validations
entering save in persistence

leaving save in persistence
leaving save in validations
leaving save in attribute_methods
leaving save in transactions
```

## Links

- [Human page](https://www.bigbinary.com/blog/live-of-save-in-activerecord)
