Straight to the Point
In order to make your Ruby constants not accessible to the outside world, Ruby gives us the private_constant method.
class Phrase
RE = REGULAR_EXPRESSION = { words: /\b[\w']+\b/ }.freeze
private_constant :RE, :REGULAR_EXPRESSION
private
attr_reader :phrase
def initialize(phrase)
@phrase = phrase.downcase
end
def words
phrase.scan(RE[:words])
end
public
def word_count
words.tally
end
end
Why
One main concern in OOP design is the balance between what to make accessible in a class’s public interface and what to not. By default, Ruby makes all constants accessible to the outside world, and you can check the available constants by using the #constants method.
irb(main): 001:0> Math.constants
=> [:DomainError, :PI, :E]
Wrapping information inside a constant can improve readability and reusability. For instance, if we just used the value 2.7182... we may not notice that it stands for the Euler’s number. However if Math::E is called, then chances are that the value is going to make sense.
In the first code snipped, a constant was used to hold the regexp value. Creating a regexp dictionary is a common practice to improve the it’s readability. So now instead of using phrase.scan(/\b[\w']+\b/) and probably wouldn’t easily remember, I can just use `phrase.scan(RE[:words]) and know that I am scanning for words.
Now, when we hit ClassName.constants our private constants won’t show up and it is going to only be accessible to our private interface.