PStore(persistent store) implements a file based persistence mechanism based on a Hash. It writes Ruby objects to an external file so it can access easily if needed. If an I/O error occurs while PStore is writing to its file, then the file will become corrupted.You can prevent this by setting pstore.ultra_safe = true. Also, it supports thread-safe and uses Marshal internally. To use this library, you must require it and instantiate a new object.
require 'pstore'
store = PStore.new("filename.pstore")
store.transaction do
#read and write transactions.
end
At the end of the transaction, all changes are committed.
Public Instance methods
Instance methods are methods that are called on an instance of a class. We can use the below methods while using PStore instances.p
[
name
]=
obj
Stores obj
in the database under the key name. When the transaction is completed, all objects accessed reflexively by obj
are saved in a file.
p
.root?(
name
)
Returns true
if the key name exists in the database.
p
.commit
Complete the transaction. When this method is called, the block passed to the transaction method is executed, and changes to the database are written to the database file.
p
.abort
Aborts the transaction. When this method is called, the execution of the block passed to the transaction method is terminated, and changes made to database objects during the transaction aren’t written to the database file.
require 'pstore'
store = PStore.new("employee.pstore")
store.transaction do
store["params"] = {"name" => "Abc", "age" => 22, "salary" => 20000 }
#commit all changes
store.commit
#retrieve data
emp = nil store.transaction { emp = store["params"] }
# Delete value
store.delete(:age)
# View all key names:
store.roots
# => :name, :salary
# abort()ing transactions will halt execution and revert all changes.
store.abort
end
In the above example, to use the library we require it at the beginning and then create a new instance for PStore called ‘store’. Next, we have to open a transaction to store and retrieve data. In that, we are storing name, age and salary of an employee into PStore by using the command,
store["params"] = {"name" => "Abc", "age" => 22, "salary" => 20000 }
Also, you can commit all the changes that you have done using the commit() method. There are methods like delete(), roots and abort() to delete the value, view all key names and revert all changes respectively.
Features of PStore
- It is stored in the persistent storage media(hard disk drives), not in volatile memory (RAM).
- The content of the data file is binary so that it can’t be edited directly with an editor.
- There exists a backup file so we can use that if the data file is corrupted.
- You can save anything you can do with Marshal.dump and you can load whatever you can do with Marshal.load.
- In PStore, all interactions happen within a transaction. So that two separate processes that are both accessing the same store will not have collisions with any modifications. Only a single transaction can be committed at any one time.
require 'yaml/store'
store = YAML::Store.new('store.yml')
After that, the YAML::Store works exactly like the PStore.
You can use PStore if it’s more important to you that reading and writing the data happens as fast as possible or if you care about the size of the created file. Otherwise, you can choose YAML::Store that provides human readability.
Also, there is another method for file storage that is SDBM. It can only store String keys and values.
You can use SDBM as:
require 'sdbm'
SDBM.open 'my_database' do |db|
db['foo'] = 'a string'
#Add / Update Many at Once
db.update({foo: 'something', bar: 1})
# Get all Values
db.each do |k,v|
puts "Key: #{k}, Value: #{v}"
end
# Retrieve Specific Value
puts db['foo']
end
So, using this we can perform the file storage which is basically Pstore without transaction feature.
Happy Coding!
Hello Anjana, nice introduction post on `PStore`. A caveat from it is: it saves binary files (since it’s marshalling Ruby objects), so if you’re trying to create config files, this could make users life a bit difficult.
Something I discovered when dealing with this problem was that Ruby’s stdlib has `YAML::Store` class, which inherits from `PStore`. You got the same syntax, same API and a nice human readable YAML file 🙂
Thanks for the comment. I will update my post with this stdlib ‘YAML::Store’.