Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I save an arbitrary Ruby object to the disk and read it back when necessary? [closed]

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?

like image 664
Konstantin Avatar asked Nov 16 '13 21:11

Konstantin


People also ask

What does .save do in Ruby?

. 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.


1 Answers

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.

like image 197
the Tin Man Avatar answered Nov 01 '22 18:11

the Tin Man