Skip to content

Instantly share code, notes, and snippets.

@joegaudet
Last active October 20, 2017 03:44
Show Gist options
  • Save joegaudet/e5aebd392ab42b6353cbc4812c634b80 to your computer and use it in GitHub Desktop.
Save joegaudet/e5aebd392ab42b6353cbc4812c634b80 to your computer and use it in GitHub Desktop.
Working out the api for snapshotting
module Snapshot
class Base
attr_accessor :snapshot_type
attr_accessor :active_record_type
# serializes attributes and relationships as a hash for storage in json B columns
def serialize
end
# @param [Object]
def self.deserialize(object)
end
def self.attribute(key)
end
def self.has_one(key, snapshot_klass)
end
def self.has_many(key, snapshot_klass)
end
end
# example
class Menu < Base
attribute :name
attribute :description
has_many :menu_groups, Snapshot::MenuGroup
end
class MenuGroup < Base
attribute :name
attribute :description
has_many :menu_items, Snapshot::MenuItem
end
class MenuItem < Base
attribute :name
attribute :description
attribute :client_price_cents
attribute :restaurant_price_cents
has_many :menu_option_groups, Snapshot::MenuOptionGroup
end
class MenuOptionGroup < Base
attribute :description
has_many :menu_option_items, Snapshot::MenuOptionItem
end
class MenuOptionItem < Base
attribute :description
attribute :client_price_cents
attribute :restaurant_price_cents
end
module SnapshotSupport
def self.snapshot(relationship, relationships_klass)
end
end
end
class Order < ActiveRecord::Base
include SnapshotSupport
belongs_to :menu
# This macro will create the following accessor
snapshot :menu, Snapshot::Menu
def menu
# memoize the menu snap shot with either the stored snapshot or one we find and
# generate from the menu_id
@menu_snapshot ||= Snapshot::Menu.deserilize(snapshot_menu) || Snapshot::Menu(Menu.find(menu_id))
end
def menu=(menu)
menu_id = menu.id
snapshot_menu = Snapshot::Menu.serialize(snapshot_menu)
end
end
class OrderItem
include SnapshotSupport
belongs_to :menu_snapshot, through: :order
has_one :menu_item
has_many :menu_option_items
provides :menu_option_items, from: :menu_snapshot
provides :menu_item, from: :menu_snapshot
# this gets meta programmed from the provides method
def menu_item
if menu_snapshot.present?
menu_snapshot.find(menu_item, menu_id)
else
super
end
end
# to many
def menu_option_items
if menu_snapshot.present?
menu_option_items.pluck(:id).map {|id| menu_snapshot.find(menu_option_item, menu_id) }
else
super
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment