简体   繁体   中英

Adding methods to base ruby class in rails

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM