Ruby > Psych -> How to parse yaml docs in to ruby objects - ruby

I'm trying to do the following:
open and read a file with multiple yaml docs
parse yaml docs into ruby objects
print content of each ruby object
and the code:
yml_string = Psych.dump(File.read(infile))
Psych.load_stream(yml_string) .each do |mobj|
puts "mobj:\n #{mobj}"
end
The puts prints the contents of the yml_string (multiple yaml docs) but it is one long string. How does one go about parsing each yaml doc from the yml_string and store them in to ruby objects?
The contents of infile (based on OP's comment):
---
member:
country: AF
phone1: 60 223-4564
phone2: +93 799 123-456
---
member:
country: BR
phone1: +55 55 2000 3456
phone2: 55 9000 1234
---
member:
country: CA
phone1: 604 423-4567
phone2: +1 604 423-4567

This is what I ended up with
yaml_hash = Psych.load_stream(File.read(infile))
yaml_hash.each do |member|
mem = Hash[member['member']]
end
Thank you for all your help.

require 'yaml'
require 'pp'
infile = "test.yml"
pp YAML.load_stream(File.read(infile))
# [{"member"=>
# {"country"=>"AF", "phone1"=>"60 223-4564", "phone2"=>"+93 799 123-456"}},
# {"member"=>
# {"country"=>"BR", "phone1"=>"+55 55 2000 3456", "phone2"=>"55 9000 1234"}},
# {"member"=>
# {"country"=>"CA", "phone1"=>"604 423-4567", "phone2"=>"+1 604 423-4567"}}]
On recent MRI psych is the same as yaml lib
p [RUBY_VERSION, YAML == Psych]
["2.0.0", true]
p [RUBY_VERSION, YAML == Psych]
["1.9.3", true]

Related

ruby yaml don't remove header %YAML 1.1

I have a array in ruby named array, I aded value into yaml file, but after in file.yml, it remove me %YAML 1.1, so I won't
yaml_string = File.read "file.yaml"
data = YAML.load yaml_string
array.each do |value|
data["title"] <<"- "+value+"\n"
end
output = YAML.dump data
File.write("file.yaml", output)
before execution, the header is present, but after execution it remove it (%YAML 1.1) and all lines comment with #, so I won't
I think something like this is what you're trying to do.
I'm assuming your yaml array of titles matches your array object.
Otherwise you could just use something like Enum#with_index if you just want to map the number of the yaml array to the text.
require 'psych'
filename = "sample_yaml.yml"
array = [0, 1, 2, 3]
if File.exists?(filename)
puts "File exists. :) Parsing the yaml file."
yaml = Psych.load_file(filename)
array.each do |value|
yaml[value]["title"] << " - #{value}" # find the title that matches the index number of array
end
else
raise ArgumentError, "bad file name"
end
puts "Outputting to reformatted yaml file"
File.open("reformatted_file.yaml", 'wb') {|f| f.write "%YAML 1.1\n" + Psych.dump(yaml)}
assuming yaml file like such
---
- title: zero
- title: one
- title: two
- title: three
Outputs
---
- title: zero - 0
- title: one - 1
- title: two - 2
- title: three - 3

I have an issue with require 'yaml' ,anyone can shed any light?

This is my code:
require 'yaml'
class Person
attr_accessor :name, :age
end
yaml_string = <<END_OF_DATA
---
-!ruby/object:Person
age: 45
name: Jimmy
- !ruby/object:Person
age:23
name: Laura Smith
END_OF_DATA
test_data = YAML::load(yaml_string)
puts test_data[0].name
puts test_data[1].name
This is the result I get:
ruby yaml1.rb
C:/Ruby200/lib/ruby/2.0.0/psych.rb:205:in parse': (<unknown>): mapping values are not allowed in this context at line 3 column 4 (Psych::SyntaxError)
from C:/Ruby200/lib/ruby/2.0.0/psych.rb:205:inparse_stream'
from C:/Ruby200/lib/ruby/2.0.0/psych.rb:153:in parse'
from C:/Ruby200/lib/ruby/2.0.0/psych.rb:129:inload'
from yaml1.rb:17:in `'
Exit code: 1
According to the book i'm reading (Beggining Ruby by Peter Cooper). My result should be like the one below:
Jimmy
Laura Smith
Anyone know why this is happening ? What am I doing wrong ?
Your YAML is not formatted properly, I guess wrote it by hand. Here's a correct version
---
- !ruby/object:Person
age: 45
name: Jimmy
- !ruby/object:Person
age: 23
name: Laura Smith
In case you didn't spot the differences, here they are
The entries age: ... and name: ... need to be indented
A space was missing in the second line (-!ruby/object:Person) between the dash (-) and the bang (!)
A space is needed between the number 23 and the colon in the line age:23

Extracing words from a string?

I have a string "---\n- bb\n- j2me\n". I want to extract the words and save it into an array. Like ['bb','j2me']. I tried the below but its not working.
"---\n- bb\n- j2me\n".split("\n")
If you have any idea please share.
That looks like YAML:
puts "---\n- bb\n- j2me\n"
# ---
# - bb
# - j2me
You can parse it with:
require 'yaml'
YAML.load("---\n- bb\n- j2me\n")
#=> ["bb", "j2me"]

How do I print the values of hashsets that are saved in a file in ruby

I have file (named ter.txt) that contains the hashsets content as below:
{"qty"=>"gfg", "unit"=>"gfg", "item"=>"xcv", "cost"=>"0.0", "salestax"=>"0.0"}
{"qty"=>"gdf", "unit"=>"g", "item"=>"gg", "cost"=>"0.0", "salestax"=>"0.0"}
I want to print the values of the hashsets. I've tried the following but I got an error of undefined local variable or method 'item'
file = File.open('ter.txt', 'r').map { |line| line.split("\n")[0] }
file.each do |hash|
p hash
p " #{hash[item]}"
end
You shouldn't save your data this way. This is a perfect case to use YAML. Write your file like:
---
- qty: gfg
unit: gfg
item: xcv
cost: 0.0
salestax: 0.0
- qty: gdf
unit: g
item: gg
cost: 0.0
salestax: 0.0
Then you can load it with:
require 'yaml'
data = YAML.load(File.read 'ter.txt')
I saved your data in a file called test.rb file firstly. The I opened the file, and read each line and substitute all => to :, to make this as a json string. Then used JSON::parse method to transform each line of json string to Hash object. Here is the code I wrote to solve your problem :-
require 'json'
File.foreach("#{__dir__}/test.txt") do |line|
p JSON.parse(line.strip.gsub("=>", ":")).values
end
Now I run the code from command prompt and got the output as you are looking for :-
arup#linux-wzza:~/Ruby> ruby -vw test.rb
ruby 2.0.0p451 (2014-02-24 revision 45167) [i686-linux]
["gfg", "gfg", "xcv", "0.0", "0.0"]
["gdf", "g", "gg", "0.0", "0.0"]
arup#linux-wzza:~/Ruby>

Use file's contents in Ruby

My "information" file includes following hash.
student_balances = {"Jane Doe"=>1000, "Jim Doe"=>6200, "John Newman"=>73282, "Leonard Smith"=>3992, "Loe Newton"=>5643, "Eric"=>34234}
I want to import this "information" file into my main program and use its contents right away.
file_location = "Ruby/account.rb"
f = File.open(file_location, "r+")
student_balances.each do |key, value|
puts "#{key} : #{value}"
end
I can't figure out how.
I would suggest to store the data in another format like YAML. It is more readable and easier to write:
# in balances.yml
"Jane Doe": 1000
"Jim Doe": 6200
"John Newman": 73282
"Leonard Smith": 3992
"Loe Newton": 5643
"Eric": 34234
Read the file with:
require 'yaml'
balances = YAML.load_file('balances.yml')
When the input files contains the following string and you will like
to import the string in a ruby variable you first have to evaluate the
string. Then you can use the variables as an array
student_balances = nil
DATA.readline.each do | line |
eval line
puts student_balances
end
__END__
student_balances = {"Jane Doe"=>1000, "Jim Doe"=>6200, "John Newman"=>73282, "Leonard Smith"=>3992, "Loe Newton"=>5643, "Eric"=>34234}

Resources