Reputation: 194
I want to extend the Nokohiri::XML::Node
object into my own unique object with custom behaviors (methods).
I have the following object:
class RDFNode < Nokogiri::XML::Node
def get_tag
self.at_xpath("Path/to/tag")
end
end
and the Node Factory:
class RDFNodeFactory
@doc = Nokogiri::XML.parse('rdf_file.xml')
def self.get_node(id)
@doc.xpath_at("Path/to/rdf/node[@id=#{id}]")
end
end
My question is about best Ruby practices and basic OOP in Ruby.
How can I get RDFNodeFactory.get_node("someid")
to return an RDFNode
instead of a Nokogiri::XML::Node
? I used to use type casting in Java but we don't have that in Ruby.
Should I just modify Nokogiri::XML::Node
class instead of extending it to a custom class? What is a more acceptable practice?
Upvotes: 0
Views: 972
Reputation: 194
A (sort of) solution I have is containment
class RDFNode
attr_reader :node
def initialize(node)
@node = node
end
def get_tag(id)
node.at_xpath("Path/to/tag")
end
end
Now I have preserved modularity but lost all the awesomeness of inheritance! Not perfect but it's a start. Perhaps there is some way improve on this (extend RDFNode with Nokogiri::XML::Node and make self = node for Nokogiri methods)?
Upvotes: 0
Reputation: 64147
Instead of extending the Nokogiri::XML::Node
class just to add one method, you should move the get_tag method and add it to the already existing Nokogiri::XML::Node
using the concept of Open Classes. This would look like:
class Nokogiri::XML::Node
def get_tag
self.at_xpath("Path/to/tag")
end
end
This is completely fine in terms of Ruby Standards, just be sure there aren't any side affects when adding this method to Nokogiri::XML::Node, such as get_tag already exists.
With regards to open class(under the assumption that there are no current conflicts) vs inheriting 3rd party libraries:
This is a valid fear, this is why you have to be very careful when you utilize open classes and updating 3rd party libraries. However if you think of it, if a library changes their code in such a way that it messes up your code... This will happen both when you use open classes or inherit from their code. When it all boils down, you have a dependency, and you must be careful no matter what.
Upvotes: 3
Reputation: 238
Instance methods tied to object, not class, so there is no way to "cast" object to another class. But in ruby you can add methods to existing class:
class Nokogiri::XML::Node
def get_tag
self.at_xpath("Path/to/tag")
end
end
Or even add method to single object:
def @doc.get_tag
self.at_xpath("Path/to/tag")
end
Upvotes: 1