Application Document

An application document is a persistable model with a global id, timestamps, an audit log, and life cycle callbacks providing hooks for callbacks workers. An application document cleans some of its data before validation and before create.


Workarea employs Mongoid (docs, source), MongoDB's ODM written in Ruby, to map between in-memory models and documents persisted to disk.


An application document includes the Mongoid::Document module (docs, docs), providing a large API for document persistence, queries, relations, callbacks, validations, indexes, and more.


An application document also includes Mongoid's Mongoid::Timestamps module (docs), which provides timestamp fields and accessor methods such as ApplicationDocument#created_at and ApplicationDocument#updated_at.

Audit Log

An application document additionally includes the Mongoid::AuditLog module (docs) from the mongoid-audit_log library (docs, source). This library provides basic audit logging for each application document. ApplicationDocument#audit_log_entries provides access to the audit log entries for an application document instance.

Global ID

An application document includes GlobalID::Identification (docs), providing the model with a global id that is guaranteed to be unique within the application, independent of its type.

Callbacks Workers

An application document includes Sidekiq::Callbacks, providing ApplicationDocument#run_callbacks, an extension of ActiveSupport::Callbacks#run_callbacks (docs) allowing callbacks workers to run or enqueue in response to the document's life cycle callbacks, such as after_save and after_destroy.

Data Cleaning

An application document cleans array fields before validation and ensures default locale values before create.

Reject Blank Array Members

Before validation, each field value of type Array is cleaned to remove blank members.

category = ['color', '', nil, 'size'])

# => ["color", "", nil, "size"]


# => ["color", "size"]

Ensure Default Locale Values

Before create, for each localized field with a value, the value is copied to the default locale if that value is blank within the default locale. Ensuring a value for the default locale avoids a class of errors when locales switch or fall back.

# => :en

# => :en

# change to non-default locale
I18n.locale = :fr

# => :fr

# within this locale, create a product with a name (a localized field)
red_dress = Workarea::Catalog::Product.create!(name: 'Robe Rouge')
# => "Robe Rouge"

# switch back to the default locale
I18n.locale = I18n.default_locale

# the 'name' value from the :fr locale has been copied to the :en locale to
# avoid errors when switching or falling back
# => "Robe Rouge"

# red_dress.name_translations
# => {"fr"=>"Robe Rouge", "en"=>"Robe Rouge"}