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