Created
April 20, 2023 00:10
-
-
Save notEthan/b8dd826eff666e8b30438f1988c7d707 to your computer and use it in GitHub Desktop.
JSI filter serialized ActiveRecord
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
require 'jsi' | |
# db/model setup | |
require 'active_record' | |
dbpath = Pathname.new("tmp.sqlite3") | |
dbpath.unlink if dbpath.exist? | |
at_exit { dbpath.unlink } | |
ActiveRecord::Base.establish_connection( | |
:adapter => "sqlite3", | |
:database => dbpath | |
) | |
ActiveRecord::Schema.define do | |
create_table :users do |table| | |
table.column :name, :string | |
table.column :email, :string | |
table.column :age, :integer | |
table.column :secret, :string | |
end | |
end | |
class User < ActiveRecord::Base | |
end | |
# record β JSON | |
user = User.create!( | |
name: 'Me', | |
email: 'me@here', | |
age: 0, | |
secret: 'π€', | |
) | |
user_json = user.serializable_hash # using ActiveRecord's builtin serialization | |
puts "json" | |
pp user_json | |
# β {"id" => 1, "name" => "Me", "email" => "me@here", "age" => 0, "secret" => "π€"} | |
# Filtering by _described_ attributes | |
user_schema = JSI.new_schema({ | |
"$schema" => "http://json-schema.org/draft-07/schema", | |
"type" => "object", | |
"properties" => { | |
"id" => {}, | |
"name" => {"type" => "string"}, | |
# β no "email" | |
"age" => {"type" => "integer", "minimum" => 1}, | |
# β no "secret" | |
}, | |
}) | |
user_jsi = user_schema.new_jsi(user_json) | |
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node| | |
# reject nodes which have no schemas that describe them | |
!node.jsi_schemas.empty? | |
end | |
puts "filter described attributes: no email, no secret" | |
pp user_filtered | |
# β #{<JSI> "id" => 1, "name" => "Me", "age" => 0} | |
# Filtering by _excluded_ attributes with `false` schema | |
user_schema = JSI.new_schema({ | |
"$schema" => "http://json-schema.org/draft-07/schema", | |
"type" => "object", | |
"properties" => { | |
"id" => {}, | |
"name" => {"type" => "string"}, | |
# β "email" is not specifically excluded | |
"age" => {"type" => "integer", "minimum" => 1}, | |
"secret" => false, # β will exclude "secret" | |
}, | |
}) | |
user_jsi = user_schema.new_jsi(user_json) | |
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node| | |
# reject nodes described by `false` schema | |
!node.jsi_schemas.any? { |s| s.schema_content == false } | |
end | |
puts "filter excluded attributes: no secret" | |
pp user_filtered | |
# β #{<JSI> "id" => 1, "name" => "Me", "email" => "me@here", "age" => 0} | |
# Filtering by _valid_ attributes (this seems like a bad idea but worth illustrating) | |
user_schema = JSI.new_schema({ | |
"$schema" => "http://json-schema.org/draft-07/schema", | |
"type" => "object", | |
"properties" => { | |
"id" => {}, | |
"name" => {"type" => "string"}, | |
# β "email" has no schema, nothing makes it invalid | |
"age" => {"type" => "integer", "minimum" => 1}, # β age=0 fails validation | |
"secret" => false, # β nothing is valid against `false` schema | |
}, | |
}) | |
user_jsi = user_schema.new_jsi(user_json) | |
user_filtered = user_jsi.jsi_select_descendents_leaf_first do |node| | |
node.jsi_valid? | |
end | |
puts "filter valid attributes: no age, no secret" | |
pp user_filtered | |
# β #{<JSI> "id" => 1, "name" => "Me", "email" => "me@here"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment