I would like to save a Ruby set, or a hash, to the disk and it back from the file when necessary. How can I do this?
. save is an “Instance Method”, it returns either true or false depending on whether the object was saved successfully to the database or not. If the model is new, a record gets created in the database, otherwise the existing record gets updated.
A set is basically a hash with the value for each key/value pair set to the same values. It's the key that makes it behave like a set.
Once we know that, saving and restoring a Set is just like saving an Array or a Hash, and can be done in a number of ways.
@steenslag mentions using Marshall.dump
, which is good.
Because a Set is a variant of a Hash, you can also use YAML or JSON to serialize the data. The big advantage to either is that they are easy to reuse in other languages. YAML and JSON are commonly used to store and transfer data between hosts and are very readable formats.
Here are some examples to give you ideas:
require 'set'
require 'json'
require 'yaml'
foo = Set.new
foo << 1
foo << 2
foo << 1
foo # => #<Set: {1, 2}>
foo
is a Set. It can also be converted to an Array:
foo.to_a # => [1, 2]
We can use YAML to serialize the Set:
puts YAML.dump(foo)
# >> --- !ruby/object:Set
# >> hash:
# >> 1: true
# >> 2: true
And, we can create the serialized version, then parse it again back into a Set:
YAML.load(YAML.dump(foo)) # => #<Set: {1, 2}>
Because foo
is a Set, we can also convert it to an Array, and then use YAML to serialize that:
puts YAML.dump(foo.to_a)
# >> ---
# >> - 1
# >> - 2
Then we can read the data back in, and, if we choose, convert it back to a Set:
bar = YAML.load(YAML.dump(foo.to_a)).to_set
bar.class # => Set
bar # => #<Set: {1, 2}>
Or, if it's a language that is reading the YAML, that doesn't support Set, like Perl, it can be left as an Array when the Perl code reads and parsed the data.
JSON works similarly. Here's an example of a round-trip of the data via Array:
foo.to_a.to_json # => "[1,2]"
JSON.parse(foo.to_a.to_json) # => [1, 2]
JSON.parse(foo.to_a.to_json).to_set # => #<Set: {1, 2}>
JSON also has the []
method, which is smart enough to figure out whether the parameter passed in is a String or an Array or Hash. If it's the first the parameter is parsed and returned as a Ruby object. If it's the later two, it's serialized and turned into a string:
JSON[foo.to_a] # => "[1,2]"
JSON[JSON[foo.to_a]] # => [1, 2]
JSON[JSON[foo.to_a]].to_set # => #<Set: {1, 2}>
In either case of using JSON or YAML, reading and writing the resulting string is easily done using several different IO or File methods. Look at File.write and File.read, both inherited from IO, and, if you decide to work with YAML, look at YAML.load_file
, which is inherited from Psych.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With