Skip to content

Instantly share code, notes, and snippets.

@havenwood
Created May 23, 2019 21:40
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 havenwood/f23bd816ce5535132fbcffe0d028179a to your computer and use it in GitHub Desktop.
Save havenwood/f23bd816ce5535132fbcffe0d028179a to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require 'securerandom'
require 'yaml/store'
##
# Just an example hardcoded for now:
FIELDS = { first_name: :string, last_name: :string, age: :integer }.freeze
Person = Struct.new(*FIELDS.keys, keyword_init: true)
class Psyche
include ActiveModel::Attributes
include ActiveModel::Dirty
include ActiveModel::Serializers::JSON
include ActiveModel::Model
extend Enumerable
STORE = YAML::Store.new Rails.root.join('config', 'psyche.store'), true
STORE.ultra_safe = true
##
# Seeding the store:
if STORE.transaction { STORE.roots.empty? }
STORE.transaction do
STORE[SecureRandom.uuid] = Person.new first_name: 'Arav', last_name: 'Smith', age: 32
STORE[SecureRandom.uuid] = Person.new first_name: 'Mary', last_name: 'Ami', age: 101
end
end
attr_accessor :persisted
FIELDS.each do |field, type|
attribute field, type
define_method "#{field}=" do |value|
public_send "#{field}_will_change!"
super(value)
end
end
attribute_method_suffix '?'
define_attribute_methods(*FIELDS.keys)
def attribute?(attr)
public_send(attr).present?
end
validates :first_name, presence: true
def initialize(attributes = {})
super()
@persisted = false
assign_attributes(attributes) if attributes
yield self if block_given?
end
def persisted?
@persisted
end
def persist!
changes_applied
@persisted = true
end
def pretty_print(pp)
pp.object_address_group self do
pp.breakable
*head, tail = attributes.to_a
head.each do |field, value|
pp.text "#{field}=#{value.inspect}"
pp.comma_breakable
end
pp.text "#{tail.first}=#{tail.last.inspect}"
end
end
def inspect
attrs = attributes.map { |field, value| "#{field}: #{value.inspect}" }.join(', ')
"#<#{self.class}:#{format '%#018x', object_id << 1} #{attrs}>"
end
class << self
def find(id)
STORE.transaction do
record = STORE[id]
raise KeyError, "no record found for id `#{id}'" unless record
new record.to_h
end
end
def all
STORE.transaction do
STORE.roots.map do |id|
new STORE[id].to_h
end
end
end
def each
all.each { |record| yield record }
end
def create(attributes = OpenStruct.new)
yield attributes if block_given?
STORE.transaction do
STORE[SecureRandom.uuid] = Person.new attributes.to_h.symbolize_keys
end
end
def update(id, attributes)
STORE.transaction do
attributes.to_h.symbolize_keys.each do |key, value|
STORE[id][key] = value
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment