Skip to content

Latest commit

 

History

History
78 lines (67 loc) · 2.78 KB

20220810081621-yaml_store_marshal_and_storing_data.org

File metadata and controls

78 lines (67 loc) · 2.78 KB

YAML::Store, Marshal and storing data

Need to store data or objects to be used later? Maybe as a file or in a document database? This could help.

Storing data in YAML

YAML lib

I think to_yaml is from the Psych library. See Psych#dump for options that can be passed to to_yaml

require 'yaml'
Person = Struct.new :first_name, :last_name
people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")]
     
yaml = people.to_yaml
# => "---\n- !ruby/struct:Person\n  first_name: Bob\n  last_name: Smith\n- !ruby/struct:Person\n  first_name: Mary\n  last_name: Johnson\n"
     
YAML.safe_load(yaml, permitted_classes: [Person, Symbol])
# => => [#<struct Person first_name="Bob", last_name="Smith">, #<struct Person first_name="Mary", last_name="Johnson">]

In a file

require 'yaml'
File.open('things.yml', 'w') do |file|
  YAML.dump(["banana", "coffee", "skittles"], file)
end
friends = YAML.load(File.open('things.yml'))
File.delete('things.yml')

YAML::Store

This is the basic example from the docs, however, I found that in Ruby 3.1 errors such as Tried to load unspecified class: Person (Psych::DisallowedClass) were raised. In order to work around it, used safe_load and permitted classes option.

require 'yaml/store'
Person = Struct.new :first_name, :last_name
people = [
  Person.new("Bob", "Smith"), 
  Person.new("Mary", "Johnson")
  ]
store = YAML::Store.new "test.store" # creates a file test.store
store.transaction do
  store["people"]   = people  
  store["greeting"] = { "hello" => "world" }
end
data = YAML.safe_load(File.open('test.store'), permitted_classes: [Person, Symbol])
File.delete('test.store')

Formatting YAML values

See this this SO post

Storing data using Marshal

This stores data in a binary format. The data is turned into a byte stream.

File.open('friends.sav', 'w') do |file|
  Marshal.dump(["fred", "bert", "mary"], file)
end
friends = Marshal.load(File.open('friends.sav'))
File.delete('friends.sav')

JSON

It’s worth noting that JSON could be used as well. And I think it’s faster. In this case, we can determine how an object is serialized by defining the as_json. The JSON parsed results could be passed to an initializer to create a new object with the same data.