Skip to content

Commit

Permalink
Update serialization to use MessagePack (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
hopsoft authored Nov 13, 2023
1 parent cbafe28 commit 9b0de82
Show file tree
Hide file tree
Showing 98 changed files with 3,722 additions and 1,026 deletions.
4 changes: 4 additions & 0 deletions .config/tocer/configuration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
label: "## Table of Contents"
patterns:
- "README.md"
root_dir: "."
File renamed without changes.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['3.1', '3.2']
ruby-version: ['3.0', '3.1', '3.2']
steps:
- uses: actions/checkout@v3
- name: Set up Ruby ${{ matrix.ruby-version }}
Expand Down
3 changes: 3 additions & 0 deletions .standard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignore:
- 'lib/**/*':
- Style/ArgumentsForwarding
1,125 changes: 915 additions & 210 deletions README.md

Large diffs are not rendered by default.

6 changes: 1 addition & 5 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ require "minitest/test_task"
task default: :test

Minitest::TestTask.create(:test) do |t|
t.test_globs = if ARGV.size > 1
ARGV[1..]
else
["test/**/*_test.rb"]
end
t.test_globs = ENV["GLOBS"] ? ENV["GLOBS"].split(",") : ["test/**/*_test.rb"]
end
63 changes: 63 additions & 0 deletions bin/bench
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "pry"
require "benchmark"
require "awesome_print"

require_relative "../test/rails_kit/setup"
require_relative "../lib/universalid"

@count = 5_000
@pad = 98

def run(label)
Benchmark.benchmark Benchmark::CAPTION, 52, Benchmark::FORMAT, "Average" do |x|
time = x.report(label) { @count.times { yield } }
[time / @count.to_f]
end
puts "".ljust(@pad, ".")
end

# seed data ..................................................................................................
campaign = Campaign.create_for_test
campaign.emails = Email.create_for_test(3) do |email|
email.attachments = Attachment.create_for_test(2)
end
hash = campaign.as_json(include: {emails: {include: :attachments}})
puts "Benchmarking with the following ActiveRecord/Hash data..."
puts "".ljust(@pad, "=")
ap hash

# pre/setup ..................................................................................................
hash_uid = URI::UID.build(hash)
hash_uid_string = hash_uid.to_s

active_record_uid = URI::UID.build(campaign, include_descendants: true, descendant_depth: 1)
active_record_uid_string = active_record_uid.to_s

# benchmarks .................................................................................................
puts "".ljust(@pad, "=")
puts "Benchmarking #{@count} iterations"
puts "".ljust(@pad, "=")

# PackableHash ...............................................................................................
run("URI::UID.build Hash") { URI::UID.build hash }
run("URI::UID.build Hash, include_blank: false") { URI::UID.build hash, include_blank: false }
run("URI::UID.parse HASH/UID") { URI::UID.parse hash_uid_string }
run("URI::UID.decode HASH/UID") { hash_uid.decode }

# ActiveRecord ...............................................................................................
run("URI::UID.build ActiveRecord") { URI::UID.build campaign }
run("URI::UID.build ActiveRecord, exclude_blank") { URI::UID.build campaign, include_blank: false }
run("URI::UID.build ActiveRecord, include_descendants") { URI::UID.build campaign, include_descendants: true, descendant_depth: 2 }
run("URI::UID.parse ActiveRecord/UID") { URI::UID.parse active_record_uid_string }
run("URI::UID.decode HASH/UID") { active_record_uid.decode }

# Everything .................................................................................................
run("UID > GID > UID.decode include_descendants") do
URI::UID.from_gid(URI::UID.build(campaign, include_descendants: true, descendant_depth: 2).to_gid_param).decode
end
run("UID > SGID > UID.decode include_descendants") do
URI::UID.from_sgid(URI::UID.build(campaign, include_descendants: true, descendant_depth: 2).to_sgid_param(for: "benchmarks"), for: "benchmarks").decode
end
55 changes: 0 additions & 55 deletions bin/benchmarks

This file was deleted.

3 changes: 3 additions & 0 deletions bin/c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env ruby

exec File.expand_path("./console", __dir__), *ARGV
13 changes: 2 additions & 11 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ require "bundler/setup"
require "awesome_print"
require "pry-byebug"
require "pry-doc"

require "globalid"
GlobalID.app = "UniversalID"
SignedGlobalID.app = "UniversalID"
SignedGlobalID.verifier = GlobalID::Verifier.new("UniversalID")

require "universalid"
require_relative "../test/models"

#require "irb"
#IRB.start(__FILE__)
require_relative "../test/rails_kit/setup"
require "universal_id"

Pry.start
97 changes: 49 additions & 48 deletions bin/demo
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,73 @@ require "pry-doc"
require "universalid"
require_relative "../test/models"

# ............................................................................................................
# Create a Campaign via multi-step form (wizard) running over HTTP
# ............................................................................................................
## ............................................................................................................
## Create a Campaign via multi-step form (wizard) running over HTTP
## ............................................................................................................

binding.pry
#binding.pry

# Step 1. Assign basic campaign info
campaign = Campaign.new(name: "Example Campaign", description: "Example Description")
param = campaign.to_portable_hash_gid_param
## Step 1. Assign basic campaign info
#campaign = Campaign.new(name: "Example Campaign", description: "Example Description")
#param = campaign.to_packable.to_gid_param

binding.pry
#binding.pry

# Step 2. Create first email
campaign = Campaign.new_from_portable_hash(param)
campaign.emails << campaign.emails.build(subject: "First Email", body: "Welcome", wait: 1.day)
param = campaign.to_portable_hash_gid_param
## Step 2. Create first email
#campaign = Campaign.from_packable(param)
#campaign.emails << campaign.emails.build(subject: "First Email", body: "Welcome", wait: 1.day)
#param = campaign.to_packable(methods: :emails_attributes).to_gid_param

binding.pry
#binding.pry

# Step 3. Create second email
campaign = Campaign.new_from_portable_hash(param)
campaign.emails << campaign.emails.build(subject: "Second Email", body: "Follow Up", wait: 1.week)
param = campaign.to_portable_hash_gid_param
## Step 3. Create second email
#campaign = Campaign.from_packable(param)
#campaign.emails << campaign.emails.build(subject: "Second Email", body: "Follow Up", wait: 1.week)
#param = campaign.to_packable(methods: :emails_attributes).to_gid_param

binding.pry
#binding.pry

# Step 4. Create third email
campaign = Campaign.new_from_portable_hash(param)
campaign.emails << campaign.emails.build(subject: "Third Email", body: "Hard Sell", wait: 2.days)
param = campaign.to_portable_hash_gid_param
## Step 4. Create third email
#campaign = Campaign.from_packable(param)
#campaign.emails << campaign.emails.build(subject: "Third Email", body: "Hard Sell", wait: 2.days)
#param = campaign.to_packable(methods: :emails_attributes).to_gid_param

binding.pry
#binding.pry

# Step 5. Configure final details
campaign = Campaign.new_from_portable_hash(param)
campaign.assign_attributes trigger: "Sign Up"
param = campaign.to_portable_hash_gid_param
## Step 5. Configure final details
#campaign = Campaign.from_packable(param)
#campaign.assign_attributes trigger: "Sign Up"
#param = campaign.to_packable(methods: :emails_attributes).to_gid_param

binding.pry
#binding.pry

# Step 6. Review and save
campaign = Campaign.new_from_portable_hash(param)
campaign.save!
## Step 6. Review and save
#campaign = Campaign.from_packable(param)
#campaign.save!

binding.pry
#binding.pry

# ............................................................................................................
# Create a digital product from the Campaign (i.e. template)
# ............................................................................................................
## ............................................................................................................
## Create a digital product from the Campaign (i.e. template)
## ............................................................................................................

binding.pry
#binding.pry

# 1. Create a portable digital product from the Campaign .....................................................
campaign = Campaign.first
signed_param = campaign.to_portable_hash_sgid_param(gid_options: {for: "Promotion 123", expires_in: 30.seconds})
# NOTE: The signed param is a sellable digital product with built in purpose and scarcity!
## 1. Create a packable digital product from the Campaign .....................................................
#campaign = Campaign.first
#signed_param = campaign.to_packable(except: [:id, :campaign_id], methods: :emails_attributes).to_sgid_param(for: "Promotion 123", expires_in: 30.seconds)
## NOTE: The signed param is a sellable digital product with built in purpose and scarcity!

# 2. Reconstruct the shared template (digital product) .......................................................
copy = Campaign.new_from_portable_hash(signed_param, for: "Promotion 123")
## 2. Reconstruct the shared template (digital product) .......................................................
#binding.pry
#copy = Campaign.from_packable(signed_param, for: "Promotion 123")

binding.pry
#binding.pry

# 3. Let the product expire (wait 30 seconds) ................................................................
# gid = UniversalID::PortableHash.parse_gid(signed_param, for: "Promotion 123")
invalid_copy = Campaign.new_from_portable_hash(signed_param, for: "Promotion 123")
## 3. Let the product expire (wait 30 seconds) ................................................................
## gid = UniversalID::PackableHash.parse_gid(signed_param, for: "Promotion 123")
#invalid_copy = Campaign.from_packable(signed_param, for: "Promotion 123")

binding.pry
#binding.pry

puts "End of demo."
#puts "End of demo."
2 changes: 1 addition & 1 deletion bin/loc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

cloc lib
cloc contrib lib
3 changes: 3 additions & 0 deletions bin/rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

bundle exec rake "$@"
3 changes: 3 additions & 0 deletions bin/t
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env ruby

exec File.expand_path("./test", __dir__), *ARGV
16 changes: 16 additions & 0 deletions bin/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env ruby

globs = if ARGV.size > 1
ARGV
elsif ARGV.size == 1
fuzzy = ARGV.first
fuzzy.end_with?("_test.rb") ?
["test/**/*#{fuzzy}"] :
["test/**/*#{fuzzy}**/*_test.rb", "test/**/*#{fuzzy}*_test.rb"]
end

if globs.nil?
exec "bundle exec rake test"
else
exec "bundle exec rake test GLOBS='#{globs.join(",")}'"
end
12 changes: 12 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
prepack:
exclude: []
include: []
include_blank: true

database:
include_keys: true
include_timestamps: true
include_unsaved_changes: false
include_descendants: false
descendant_depth: 0
45 changes: 45 additions & 0 deletions config/example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
##############################################################################################################
# Prepack options applied before packing with MessagePack
##############################################################################################################
prepack:
# ..........................................................................................................
# A list of attributes to exclude (for objects like Hash, OpenStruct, Struct, etc.)
# Takes prescedence over the`include` list
exclude: []

# ..........................................................................................................
# A list of attributes to include (for objects like Hash, OpenStruct, Struct, etc.)
include: []

# ..........................................................................................................
# Whether or not to omit blank values when packing (nil, {}, [], "", etc.)
include_blank: true

# ==========================================================================================================
# Database records
database:
# ......................................................................................................
# Whether or not to include primary/foreign keys
# Setting this to `false` can be used to make a copy of an existing record
include_keys: true

# ......................................................................................................
# Whether or not to include date/time timestamps (created_at, updated_at, etc.)
# Setting this to `false` can be used to make a copy of an existing record
include_timestamps: true

# ......................................................................................................
# Whether or not to include unsaved changes
# Assign to `true` when packing new records
include_unsaved_changes: false

# ......................................................................................................
# Whether or not to include loaded in-memory descendants (i.e. child associations)
include_descendants: false

# ......................................................................................................
# The max depth (number) of loaded in-memory descendants to include when `include_descendants == true`
# For example, a value of (2) would include the following:
# Parent > Child > Grandchild
descendant_depth: 0
8 changes: 8 additions & 0 deletions contrib/active_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && defined?(ActiveRecord::Relation)

require_relative "active_record/base_message_pack_type"
require_relative "active_record/relation_message_pack_type"

end
Loading

0 comments on commit 9b0de82

Please sign in to comment.