I have a very simple module, Utility
, defined in utility.rb
in the lib directory of a rails app. It just adds two simple methods to classes from Ruby standard library.
However, when I require
this file, the classes inside it don't respond to the methods I have defined here. Such as, [].concat_with
fails with a NoMethodError
. Why?
module Utility
#
# This module just contains useful functions
#
class Array
def concat_with(seperator = "")
reject! { |c| c.empty? }.join(seperator)
end
end
class Float
def flat
"%gx" % (self / 100.00)
end
end
end
That's because you've defined new classes, instead of patching existing ones. These classes are Utility::Array
and Utility::Float
. In module
-clause everything is in the module's scope.
In Ruby 2.0 refinements were added that allow for temporary patches to existing classes, which seems like your case:
module Utility
#
# This module just contains useful functions
#
refine Array do
def concat_with(seperator = "")
reject! { |c| c.empty? }.join(seperator)
end
end
refine Float do
def flat
"%gx" % (self / 100.00)
end
end
end
Then you do:
using Utility # Obviously, it has to be `required`
puts 3.14.flat
And these methods will only exist in the current scope. Once you go outside, they will vanish.
Of course, you can reference classes from outside the module, like so:
module Utility
#
# This module just contains useful functions
#
class ::Array
def concat_with(seperator = "")
reject! { |c| c.empty? }.join(seperator)
end
end
class ::Float
def flat
"%gx" % (self / 100.00)
end
end
end
But that would write the changes permanently (process-wise). Sometimes that might be desirable, but I avoid this unless absolutely necessary, as it can easily conflict with changes made by other libraries.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.