Versions of the Ruby Object

I have a series of Ruby objects that model basic XML (like OXM). Unfortunately, the XML changes and the corresponding version is clicked. I need to update my Ruby objects to be able to handle both versions. I would like to do something cleaner than a ton of if / else statements in my methods, as this is likely to happen again. Is there an idiomatic Ruby way to handle this? I was thinking about using the base class as a proxy for various "versions" of classes, i.e.

class XMLModel class V1 # V1 specific implementation end class V2; # V2 specific implementation end def initialize # create a new V? and set up delegation to that specific version of the object end def from_xml(xml_string) # use the XML string to determine correct version and return a # specific version of the object end end 

The best part about this method is that each version is different inside the code and allows me to add / remove versions with a little backward compatibility testing. The bad news is that I most likely get a lot of code duplication. In addition, in this case, XMLModel.new returns the new XMLModel , while the XMLModel.from_xml factory method returns the new XMLModel::V1 .

Ideas?

+6
source share
3 answers

I see several options for you.

You can request the proxy method on XMLModel using method_missing .

 class XMLModel def load_xml(xml) version = determine_version(xml) case version when :v1 @model = XMLModelV1.new when :v2 @model = XMLModelV2.new end end def method_missing(sym, *args, &block) @model.send(sym, *args, &block) end end 

Another option is to dynamically copy methods from a specific version to an XMLModel instance. However, I would not want to do this if it was not necessary.

The third option is to create a module for each version that has methods specific to that version. Then, instead of the proxy object, you simply enable the module for a specific version.

 module XMLModelV1 #methods specific to v1 end module XMLModelV2 #methods specific to v2 end class XMLModel #methods common to both versions def initialize(version) load_module(version) end def load_xml(xml) load_module(determine_version(xml)) end private def load_module(version) case version when :v1 include XMLMOdelV1 when :v2 include XMLModelV2 end end end 
+3
source

Why not build a subclass that inherits from XMLModel, then the solution between the classes is only at one point in the code.

 class XMLModel_V1 < XMLModel def from_xml(xml_string) # do V1 specific things end end class XMLModel_V2 < XMLModel def from_xml(xml_string) # do V2 specific things end end # Sample code wich shows the usage of the classes if(V1Needed) m = XMLModel_V1 else m = XMLModel_V2 end 
+2
source

This is not a complete answer, but only an improved formatted version of my comment describing how you can override :: new.

 class XMLModel def new *args if self == XMLModel klass = use_v1? ? XMLModelV1 : XMLModelV2 instance = klass.allocate instance.initialize *args instance else super *args end end end # and of course: class XMLModelV1 < XMLModel; end class XMLModelV2 < XMLModel; end 
+2
source

Source: https://habr.com/ru/post/892042/


All Articles