One more technique worth noting is the chained functional style of using Hash, which you can do in Ruby because Hash inherits from Enumerable. If you're prototyping a script to do some data-cleaning, this makes it easy to build up your pipeline and iterate on it. For example:
foobar = { ...your data here... }
foobar.map do |k, v|
# ...
# do some transformation here
# ...
# and then return the replacement key/value for this entry
[key, new_value]
end.select do |k, v|
# do some filtering here, e.g.:
is_foobarable?(k, v)
end.map do |k, v|
# ...
# do some expensive transformation here on the smaller data set
# ...
[key, newer_value]
end.to_h
(Note that you have to call #to_h at the end since the Enumerable functions will coerce the hash into an array of arrays.)Now your code literally shows the pipeline that your data is falling through — and each of these steps can be side-effect-free, with no mutations to the original foobar structure.