Orphanage:

A simple library for storing temporary orphan records.

Orphanage is a super lightweight library for persisting orphan records. Let's say you have some data but don't yet know all of its foreign keys. Orphanage streamlines the process of keeping it in a temporary table and then, when all foreign keys become available, transferring it to the proper table in the database.

Installation

gem 'orphanage'

A simple use case

Let's say you are have a database with students having many exams. Exam results come in to your database via an external source, but sometimes you can't match them up perfectly. A person may have a different last name due to marriage for example. When exam records can not be identified to a student they should be stored in the table exam_temps. Later when an an admin user audits the ambiguous records and provides a student, the record is transferred fromexam_temps to exams.

Usage

Model Creation

Using the generator

Assuming your home model already exists and its corresponding table exists in the database run rails generate orphanage:init <HomeModelName>. For example:

rails generate orphanage:init Exam

generates a model for your orphan table as well as a migration file that will give you all of the columns existing in the home model. You'll also get any other files you would expect when running rails generate model (such as tests, factories, fixtures, etc as the case may be)

Manually

Creating an orphan model by hand isn't much more work. By default orphanage expects the model to have Temp appended to the original, so for example an orphan model to Exam would be ExamTemp.

Then inside that model:

require 'orphanage'

class ExamTemp < ActiveRecord::Base
  include Orphanage
  orphan
end

From there you can add temporary records to this orphan table like you normally would.

Adoption

Transferring a model to its home table is done by calling the adopt method. For example:

# record can't be stored in exam table because it has no student_id
exam_temp = ExamTemp.create!({:score => 150,
  :taken_on => Date.today,
  :first_name => "Jacob",
  :last_name => "Stoebel"
})

#later, a student_id is provided for this record
exam_temp.adopt({:student_id => 1})

Calling adopt, if successful, will return the created permanent record. The temporary record will stick around unless you explicitly as for it to be destroyed (see below)

Customizations

You can customize the behavior at the model level and/or the instance level with instance level customizations taking precedence. To do so, pass in a hash with any of the following keys.

  • home The ActiveRecord model to which orphan records will be transferred to when made permanent. By default the value is generated by removing Temp from the orphan model (example: ExamTemp -> Exam)
  • destroy_on_adopt (boolean) if the orphan record should be destroyed after successful transfer of record. Defaults to false.
  • update_time_stamps a hash of booleans with the following keys
    • created if the created_at timestamp should be persisted from the orphan record. Defaults to true.
    • updated if the updated_at timestamp should be persisted from the orphan record. Defaults to true.

Examples

Let's say our orphan model is ExamTemp

# define a different home class throughout the orphan class...
orphan :home => Examination

# ... or inside just this instance
temp_exam.adopt({:student_id => 1}, {:home => Examination})

# don't destroy temp records after adoption
orphan :destroy_on_adopt => false

# for this instance, don't update the timestamps after adoption
temp_exam.adopt({:student_id => 1}, {:update_timestamps => {:created => false, :updated => false}})