ruby - How do I deserialize YAML documents from external sources and have full access on class members? -
in ruby object can transferred, i.e. serialized, yaml document saving output of "to_yaml
" method file. afterwards, yaml file can read again, i.e. deserialized, using yaml::load
method. moreover, 1 has full access on members of underlying class/object.
all of valid long i'm using ruby single platform. once serialize objects in java , deserialize them under ruby, cannot access object more because of nomethoderror
exception. due to way objects/local data types named under different systems.
given ruby class "car":
# simple class describing car # class car attr :brand, :horsepower, :color, :extra_equipment def initialize(brand, horsepower, color, extra_equipment) @brand = brand @horsepower = horsepower @color = color @extra_equipment = extra_equipment end end
creating simple instance:
# creating new instance of class 'car' ... porsche = car.new("porsche", 180, "red", ["sun roof", "air conditioning"])
calling porsche.to_yaml
results in following output:
--- !ruby/object:car brand: porsche color: red extra_equipment: - sun roof - air conditioning horsepower: 180
i test deserialization loading yaml output:
# reading existing yaml file file system sample_car = yaml::load(file.open("sample.yaml")) puts sample_car.brand # returns "porsche"
this works expected, let's assume yaml document produced different system , lacks reference ruby, although having yaml-conform object description, "!car
", instead of "!ruby/object:car
":
--- !car brand: porsche color: red extra_equipment: - sun roof - air conditioning horsepower: 180
this code:
# reading existing yaml file file system sample_car = yaml::load(file.open("sample.yaml")) puts sample_car.brand # returns "porsche"
returns exception:
/path/yaml_to_object_converter.rb.rb:27:in `<main>': undefined method `brand' #<yaml::domaintype:0x9752bec> (nomethoderror)
is there way deal objects defined in "external" yaml documents?
for me sample_car
in irb shell evaluates to:
=> #<syck::domaintype:0x234df80 @domain="yaml.org,2002", @type_id="car", @value={"brand"=>"porsche", "color"=>"red", "extra_equipment"=>["sun roof", "air conditioning"], "horsepower"=>180}>
then issued sample_car.value
:
=> {"brand"=>"porsche", "color"=>"red", "extra_equipment"=>["sun roof", "air conditioning"], "horsepower"=>180}
which hash. means, can construct your car object adding class method car
so:
def self.from_hash(h) car.new(h["brand"], h["horsepower"], h["color"], h["extra_equipment"]) end
then tried it:
porsche_clone = car.from_hash(sample_car.value)
which returned:
=> #<car:0x236eef0 @brand="porsche", @horsepower=180, @color="red", @extra_equipment=["sun roof", "air conditioning"]>
that's ugliest way of doing it. there might others. =)
edit (19-may-2011): btw, figured lot easier way:
def from_hash(o,h) h.each { |k,v| o.send((k+"=").to_sym, v) } o end
for work in case, constructor must not require parameters. can do:
foreign_car = from_hash(car.new, yaml::load(file.open("foreign_car.yaml")).value) puts foreign_car.inspect
...which gives you:
#<car:0x2394b70 @brand="porsche", @color="red", @extra_equipment=["sun roof", "air conditioning"], @horsepower=180>
Comments
Post a Comment