Skip to content

Instantly share code, notes, and snippets.

@alan-andrade
Last active December 21, 2015 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alan-andrade/6325305 to your computer and use it in GitHub Desktop.
Save alan-andrade/6325305 to your computer and use it in GitHub Desktop.
My notes on trying to understand how Active record works.

ActiveRecord 3.2

Base

This class wraps all the other ActiveRecord Modules into one so that you can inherit from it and get a Class persisted by a DB.

One of the main things that happen when you Inherit from Base, is to check for STI (single table inheritance).

ActiveRecord::Persistence

Class methods that implements CRUD functions such as:

  • create
  • save
  • destroy
  • delete
  • update_attributes
  • update_attribute
  • toggle
  • increment
  • etc...

QueryCache::ClassMethods

It's basically a proxy to communicate with connection that will be the one doing the caching work.

this is not included under AR::Base

Also has a middleware piece that turns the caching on/off depending on configurations.

ActiveSupport::Benchmarkable

for later analysis.

ActiveSupport::DescendantsTracker

for later analysis.

Querying

Delegates every query method to scoped. It only implements find_by_sql & count_by_sql

ReadOnly Attributes

It stores in a class attribute the methods will be read only.

ModelSchema

Handles table names, STI table name, sequences, column names. It does all of this by communicating with connection.

Translation

Hook the lookup ancestors path ( an array of classes to poke for translation).

Inheritance

spawns the store_full_sti_class variable and sets it to true, saying that this AR class supports STI.

It ensures that when we do inherit from AR::Base, the db tables keep consistency.

Scope

Implements the with_scope that will collect queries using nested blocks.

DynamicMatchers

Implements nasty metaprogramming that let us do things like find_by_user_name.

Dig into DynamicFinderMatch and DynamicScopeMatch for more info.

Sanitization

Converts most object types into a SQL secure string.

Attribute Assignment

Implements the attributes= and assign_attributes method that will sanitizate the hash depending on mass assignment security policies.

Integration

Implements to_param and cache_key in order to play nice with ActionPack. It will use the first method to generate urls.

Validations

Implements create! and save!. These two will raise and exception when validations go wrong.

It includes ActiveModel::Validations, delegates to super on save and save!

CounterCache

It controls and caches the id autoincrement counters. With this you can reset the cache, increment/decrement the counter.

Locking

Optimistic locking will use a column in the db to know what version the row is on.

Pesimistic locking will just block the row from being queried and it uses the db locking system.

AttributeMethods

It's doing a lot related with attributes, its a layer that provides a Mutex to the instance. It heavily relies on ActiveModel::AttributeMethods.

This will genereate all the magic with method names. It includes modules like Dirty, PrimaryKey among others.

Callbacks

It heavily uses ActiveModel::Callbacks. It's just the glue between AR and AM::Callbacks

Associations

Proxies all the association method to Builder::#{Association} and implements the association(name) that will return the association instance, not the associated object.

This includes everything under /association/*

Identity Map

Cache repository where queryied items are stored to avoid double query. Stored in the Thread to make it accesible everywhere.

Comes with middleware adpater to switch it on/off.

AutosaveAssociation

It puts some steroids on Association::Builder by overriding the build method. Whe this method gets called, we define the autosave callbacks.

This piece builds the beautiful error hash when you have associated models with validation errors.

customer: 'address.state' => 'Not included in valid states.'

Nested Attributes

Handles the accepts_nested_attributes_for

This will proxy the {assocaition}_attributes= method to the convinient method depending if its a single or collection association.

Behind the scenes, is doing a simple build_{association} with the attributes that you passed as {association}_attributes.

Aggregation

Implements composed_of , which is very complex and will be deprecated in Rails 4... according to @jose_valim

Transactions

This delegates the transaction to the connection, but puts some logic before so that we do rollbacks, savepoints, etc...

Also wires the after_rollback and after_commit callbacks.

Implements save, create and save! that will be wrapped around transactions.

Reflection

It gives the class a reflections = {} attribute where all the association reflections will be stored.

customer: ActiveRecord::Reflection::AssociationRefelction...

This is to interogate Active Record classes about their associations and aggregations.

Connection

How ActiveRecord communicates with the DB ?

ConnectionSpecification

This is the last thing ActiveRecord::Base requires. This will give the ability to load or set a configuration to conect with the db.

It gives ActiveRecord::Base a connection method which will return the active connection.

To get the connection, it uses a connection handler which has a pool of connections and It'll pick the correct one. The ConnectionPool handles concurrency by using the MonitorMixin.

Relation

query methods

Here is where all arel magic happens. joins, selects, order, etc...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment