symbols - Pass Ruby object's instance variables to another class's initializer as a map -
i'm using xml-mapping gem read xml, , want feed mapping objects initializers existing domain classes. given xml like:
<foo bar="baz"><qux>quux</qux></foo> i object like:
#<foo @bar="baz", @qux="quux"> i want feed domain class like:
class myfoo def initialize(bar:, qux:) # ... etc. end end (note in myfoo attributes read-only, , there's validation , transformation goes on in initializer, it's not matter of copying instance variables 1 other.)
i tried transforming instance variables map, thus:
foo.instance_variables.map { |name| [name, foo.instance_variable_get(name)] }.to_h which produces:
{ :@bar->"baz", :@qux->"quux" } this almost need myfoo initializer, not quite -- need is
{ :bar->"baz", :qux->"quux" } is there way transform instance variable names symbols without @-sign?
alternatively, there easier way "initialize attributes in object"?
andrey's comment works fine, dislike relying on instance variables directly. suggest adding custom to_h method foo class. tie in xml-mapping following:
class foo # ... def self.__fields__ @__fields__ ||= all_xml_mapping_nodes.map { |r| r.instance_variable_get(:@attrname) } end def to_h self.class.__fields__.each_with_object({}) |field, acc| acc[field] = send(field) end end end then call myfoo.new(foo.to_h).
edit
as extension xml::mapping:
module xmlmappingextensions def self.included(base) base.extend(classmethods) end module classmethods def __fields__ @__fields__ ||= all_xml_mapping_nodes.map { |r| r.instance_variable_get(:@attrname) } end end def to_h self.class.__fields__.each_with_object({}) |field, acc| acc[field] = send(field) end end end and either include xmlmappingextensions in foo class, or:
module xml::mapping # note: may break xml::mapping if using method # , there more graceful way # tried , seems work fine... def self.included(base) base.send(:include, xmlmappingextensions) end end after have loaded xml::mapping , before have loaded foo class.
Comments
Post a Comment