Store
Store is a file based storage library for Crystal. It's heavily inspired by Ruby's PStore, although the API is different enough not to keep that P in the name. Store's job is to easily allow local file based persistence to any serializable data structure, avoiding problems like data corruption or race conditions.
Store requires Crystal 0.9.0.
Installation
Add this to your application's shard.yml
:
dependencies:
store:
github: porras/store
Usage
First things first, you need to require the builtin store you want to use (the only one at this point is JSON::Store
):
require "store/json"
To use it, you need to instantiate the store, passing the type of the persisted data, and a file name. The persisted data structure must be serializable in the selected format (this is checked at compile time):
json_store = JSON::Store(Array(String)).new("names.json")
We can use custom types, provided that we make them serializable using Crystal's serialization macros:
class ContactDetails
JSON.mapping({phone_number: String, address: String})
end
address_book_by_name = JSON::Store(Hash(String, ContactDetails)).new("address_book.json")
or even:
class ContactDetails
JSON.mapping({phone_number: String, address: String})
end
class AddressBook
JSON.mapping({owner: String, addresses: Hash(String, ContactDetails)})
end
address_book = JSON::Store(AddressBook).new("address_book.json")
Accessing the data
In order to read or write, we'll need to open a transaction, using the transaction
method. This method expectes a
block, to which the data will be yielded. We can of course read that data, but also mutate it, and the changes will be
saved:
store = JSON::Store(Array(String)).new("ips.json")
store.transaction do |ips|
ips << "173.194.32.216" unless ips.includes?("173.194.32.216")
end
The data will be saved (atomically, that is, all or nothing) when the block finishes.
Extension
As we saw, Store includes a generic store in JSON format. But it's easy to create our own store, if we want to a
different format (possible examples are YAML, MessagePack, Protocol Buffers, or even a custom defined format). In order
to do so, we need to inherit from Store::Base(T)
and define the methods #read(f : IO)
and #write(f : IO, data : T)
. See src/store/json.cr
for reference.
Contributing
- Fork it
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors
- porras - Sergio Gil - creator, maintainer