-
-
Save havenwood/f23bd816ce5535132fbcffe0d028179a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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