Thanks for your time!
I recently read about template pattern(in Ruby) and want to use this pattern in my codes.
My question is "where to put some commonly used functions".
Say I have TemplateRequestBody, JSONRequestBody and XMLRequestBody as following.
class TemplateRequestBody
def pretty_format
raised "called abstract method: pretty_format"
end
end
class JSONRequestBody < TemplateRequestBody
def pretty_format
# pretty format JSON
add_new_line_to_tail();
end
end
class XMLRequestBody < TemplateRequestBody
def pretty_format
# pretty format XML
escape_double_quotes();
add_new_line_to_tail();
end
end
In this example, add_new_line_to_tail() would be used by all child classes; escape_double_quotes() would be used only by some of the child classes.
Where should I implement these two functions? In TemplateRequestBody or?
Thanks!
As it always is - it depends :)
If a method will be shared across subclasses, putting it in the parent class (TemplateRequestBody) would make sense. If the methods will not be shared across the subclasses, then don't put them.
If method is going to be used by some of the classes, maybe you could think if a mixin would be a good place to store that method? Also, putting it in the parent class won't be a terrible idea.
Hope that helps!
Related
I was thinking wouldn't it be cool to have a print method defined in the Ruby Object class? Consider the following:
class Object
def print
puts self.to_s
end
end
23.times &:print
Is there any issue in having something like this? Seems like a good feature to have. It also appears easy to read.
There's already Object#inspect defined. Plus, there's already Kernel#print defined as private method in Object class and every class that inherits from it.
This method already exists in the Ruby standard library. However, it has a different name: display.
23.times &:display
# 012345678910111213141516171819202122
As you can see, it does not write a newline after the object's string representation; it is ill-suited for object inspection.
The main issue with adding methods to Object is that they become universal and may clash with similarly named methods in other libraries or in your project.
There are already multiple simple ways to output data or convert to string form in Ruby core, so the risk of a clash (on a very useful method name) likely outweighs any benefits from nicer syntax even in your own code.
If you have a smaller set of classes in your own project, where you feel this would be a useful feature to have, then this is an ideal use case for mix-ins.
Define a module:
module CanPrintSelf
def print
puts self.to_s
end
end
And include it in any class you want to have the feature:
class MyClass
include CanPrintSelf
end
my_object = MyClass.new
my_object.print
So you can have this feature if you like it, and you don't need to modify Object.
This is not specific to Ruby, but I happen to be using Ruby at the moment.
Here is a class that provides text printing functionality.
class Printer
# some static methods
def self.fancy_print(text)
# do fancy formatting
end
def self.print(text)
fancy_print(text)
end
# some instance methods
def initialize(text)
#text = text
end
def print
#somehow call fancy_print(#text)
end
end
Is it bad design to provide both instance and static methods in a class?
Sometimes I would like to keep several instances of Printer lying around. Other times, I just need to say Printer.print(text) and just grab that text without bothering to store it for later, hence resulting in a static print method and an instance print method.
No, it's not bad design.
It's completely normal–some methods are class methods, some are instance methods. I'm not sure what the perceived issue might even be. It's somewhat difficult to even find classes with only one or the other, although in Java you frequently see static utility classes.
Edit IMO the question is misleading; you're actually asking if it's bad design to have static and instance methods of the same name.
It's tricky if both are public because it isn't necessarily obvious how to use the class. In other words, is it designed to be used via the static, or instance method? Both? What's different about them? Should that difference be... differentiated by a name?
Ultimately it depends on context and usage–there's no single answer.
That's okay, I think. Here's how you would code the Printer#print method
class Printer
def print
self.class.fancy_print(#text)
end
end
There is nothing wrong with having class methods and instance methods for a specific class, as long as they make sense belonging to the class.
I.e. what does fancy_print do? Is it something specific to the Printer class. If it is, then you shouldn't worry.
On the other hand, if it is to be used for any string value, you can do something cheekier, i.e. adding this method to the string class
String.class_eval do
def fancy_print
## implementation
end
end
Now you can do "Hello".fancy_print
Hope this answer was of any use. Also write test cases!
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?
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.
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
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)?
so I have an ruby object that i need to create as a pdf and excel row and cvs row
so far I've created a new class with a method to take in the object and do the necessary stuff to produce the pdf , excel , csv
I've been reading Agile Software Development, Principles, Patterns, and Practices and it mentioned the extension method so i was going to do but since this is ruby should i just be reopening the class in the another file and added the methods on there to separate them from the main class
so
file ruby_model.rb
class RubyModel < ActiveRecord::Base
end
then do
ruby_model_pdf.rb
class RubyModel
def to_pdf
end
end
ruby_model_cvs.rb
class RubyModel
def to_csv
end
end
or should i go with with the object extension pattern?
Cheers
You should put your methods in a module and include the module in the class. This way is preferable because it's easier to see where the methods came from (in a backtrace, for example), and it's easier to reuse the methods if it turns out that they can be used in other classes too.
For example:
module Conversions
def to_pdf
end
def to_csv
end
end
class RubyModel
include Conversions
end
It might also be a good idea to put to_pdf and to_csv in different modules, unless it's the case that if you want to mix in one you always want to mix in the other.
This all assumes that the methods don't belong in the class itself, but judging from the names they don't.
If the language feature works fine, then keep it simple and use it.
Design patterns are documented workarounds for cases where the language is not expressive enough. A Ruby example would be Iterator, which is made redundant by blocks and Enumerable.
I am currently working through the Gregory Brown Ruby Best Practices book. Early on, he is talking about refactoring some functionality from helper methods on a related class, to some methods on module, then had the module extend self.
Hadn't seen that before, after a quick google, found out that extend self on a module lets methods defined on the module see each other, which makes sense.
Now, my question is when would you do something like this
module StyleParser
extend self
def process(text)
...
end
def style_tag?(text)
...
end
end
and then refer to it in tests with
#parser = Prawn::Document::Text::StyleParser
as opposed to something like this?
class StyleParser
def self.process(text)
...
end
def self.style_tag?(text)
...
end
end
is it so that you can use it as a mixin? or are there other reasons I'm not seeing?
A class should be used for functionality that will require instantiation or that needs to keep track of state. A module can be used either as a way to mix functionality into multiple classes, or as a way to provide one-off features that don't need to be instantiated or to keep track of state. A class method could also be used for the latter.
With that in mind, I think the distinction lies in whether or not you really need a class. A class method seems more appropriate when you have an existing class that needs some singleton functionality. If what you're making consists only of singleton methods, it makes more sense to implement it as a module and access it through the module directly.
In this particular case I would probably user neither a class nor a module.
A class is a factory for objects (note the plural). If you don't want to create multiple instances of the class, there is no need for it to exist.
A module is a container for methods, shared among multiple objects. If you don't mix in the module into multiple objects, there is no need for it to exist.
In this case, it looks like you just want an object. So use one:
def (StyleParser = Object.new).process(text)
...
end
def StyleParser.style_tag?(text)
...
end
Or alternatively:
class << (StyleParser = Object.new)
def process(text)
...
end
def style_tag?(text)
...
end
end
But as #Azeem already wrote: for a proper decision, you need more context. I am not familiar enough with the internals of Prawn to know why Gregory made that particular decision.
If it's something you want to instantiate, use a class. The rest of your question needs more context to make sense.