SoFunction
Updated on 2025-03-05

Detailed explanation of the operation methods of Ruby serialization and persistence storage (Marshal, Pstore)

Ruby Marshal Serialization

Marshal is the core library of Ruby. It can serialize and save some objects into a file in binary form, and then load it from the file and rebuild it into an object, that is, deserialization.

Marshal has no problem in serializing and saving basic data such as numerical values, strings, arrays, and boolean values.

But not all types of data can be serialized. Marshal performs some operations during the process of loading and rebuilding an object from a serialized file, but some content may be lost in the process of restoring it cannot serialize I0 stream objects and code class objects: Proc objects, singleton objects, anonymous classes and modules, which is its limitation.

The process of serialization and deserialization is very simple:

# a nested arrayarr = [
  %w(Perl Python PHP),
  %w(C C++ Java Golang),
  %w(Shell Powershell Cmdline)
  ]

# Serialize the arr object to save it to a file('/tmp/', "w") do |file|
  (arr, file)
end

# Deserialization('/tmp/') do |file|
  data = (file)
end

p data

() You can also specify at most how many nested object levels are allowed to be serialized through the third parameter, that is, depth, if the depth exceeds the depth, an error will be reported. Its default value is -1, which means that the depth is not checked, that is, dump all levels. For example:

arr = [
  %w(Perl Python PHP),
  [ %w(C C++), %(Java Golang) ],   #=> 3 layers  %w(Shell Powershell Cmdline)
  ]

# Serialize the arr object to save it to a file('/tmp/', "w") do |file|
  (arr, file, 4)      #=> If it is less than 4, an error will be reportedend

If you want to specify what to serialize in an object, or specify what type to serialize it to, you can write it in the classmarshal_dumpandmarshal_loadmethod. For example, only dump a portion of the data and save it as an array:

class Klass
  def initialize name, age, height 
    @name = name
    @age = age
    @height = height
  end
  
  def marshal_dump
    [@name, @age]
  end
  
  # Deserialization, arr is an array during serialization  # Finally it returns a Klass instance object  def marshal_load arr
    @name, @age = arr
  end
end

# Serialize an object of Klass, but it will only contain two attributes: name and ageobj = ("junmajinlong", 23, 170)
('/tmp/','w') do |file|
  (obj, file)
end

# Deserialize to get a Klass instance object, and set the name and age propertiesobj1 = ("/tmp/") do |file|
   file
end

p obj1
#=> #<Klass:0x00007fffcc0119f8 @name="junmajinlong", @age=23>

Obviously, a height attribute is missing during the above deserialization process. In order to make the object complete, when deserializing, it is necessary to reasonably build a new object based on the results obtained by deserialization. For example, use instance_eval() to build a new object:

def marshal_load arr
  self.instance_eval do
    initialize(*arr, 170)
  end
end

Ruby Pstore Storage

Pstore (persistence store) is a standard library for persistent storage in Ruby. It stores data in a key-value file based on Hash data type (binary), where value is the data you want to store, and key is a name for this part of the data.

In Pstore, the key is called root, and each key is a root.

Pstore is transaction-based, so the process of adding, deleting and modifying data multiple times is atomic, and can be committed and rolled back. The transaction will be terminated immediately when commit() and abort(), so the code behind them will not be executed. If commit() or abort() is not specified, it will be saved automatically when exiting transaction.

Because every time you read the store, you have to load part of the file content into memory (until the corresponding key is found), the reading efficiency is not high. Furthermore, every time you write, you need to copy most of the data of the file, so it is even less efficient. Therefore, Pstore is only suitable for data storage scenarios with a small amount of data and a small amount of read and write.

For example, persist to a file:

require 'pstore'

s = ('/tmp/')

 do
  s["p1"] = {name: "junmajinlong", age: 23, height: 170 }
  s["p2"] = {name: "junma", age: 22, height: 180}
  
  s["p3"] = {name: "jinlong", age: 24}
end

 do
  # Overwrite p2  s["p2"] = {name: "jinlong", age: 24, height: 170 } 
end   #=> automaticcommit

Read data from store file:

require 'pstore'

s = ("/tmp/")

p2 =  do
  s["p2"]
end
p p2
puts 

transaction(read_only=false)You can also specify whether the transaction is read-only. If read-only is set, any modifications to the store within the transaction will throw an error.

There are other auxiliary methods for Pstore:

[KEY]     :Get the value of the element,If the element does not exist, returnnil
delete()  :Delete elements,You can specify the default value parameters when the element does not exist
fetch()   :Get elements,If the element does not exist,Default error,Default return value can be specified  
path()    :returnpstoreFile path
root?()   :examinekeyDoes it exist  
roots()   :return所有的key

More AboutRuby serialization and persistent storage (Marshal, Pstore) operation methodPlease check the related links below