Ruby: How do I refactor code from two module class methods?

Here's the code:

module A
  class C1
    def self.grovel(x)
      return A::helper(x) + 3
    end
  end

  class C2
    def self.grovel(x)
      return A::helper(x) + 12
    end
  end
  private
  def helper(y)
    y + 7
  end
  module_function :helper
end

f = A::C1.grovel(7)
puts f
puts A::C2.grovel(25)

I'm working with legacy code, trying to avoid changing too much. I'm not sure I would have made two separate classes with the same method, as each class only contains one method, with common code. I want to extract the common code into a method that only the methods in A can see, but still have to invoke it with its fully qualified name ("A::helper").

Is there a better way of doing this? Ideally, I'd like to wrap the common code in a method (let's still call it "helper") that can be invoked from within the class grovel methods without any qualification, but isn't easily available to code outside module A.

Thanks.

2 Answers

  1. Kenneth- Reply

    2019-11-13

    Minixs are useful, when the proper inheritance can't be applied, for example, then a class must be inherit properties of the two other classes, therefore you can just use the inheritance mechanics here:

    module A
      class C
        def self.helper(y)
          y + 7
        end
      end
    
      class C1 < C
        def self.grovel(x)
          return self.helper(x) + 3
        end
      end
    
      class C2 < C
        def self.grovel(x)
          return self.helper(x) + 12
        end
      end
    end
    
    puts A::C1.grovel(7)
    puts A::C2.grovel(25)
    
  2. Kenny- Reply

    2019-11-13

    How about creating another module?

    module A
      module Helper
        def helper(y)
          y + 7
        end
      end  
    
      class C1
        class << self
          include A::Helper    
    
          def grovel(x)
            return helper(x) + 3
          end
        end
      end
    
      class C2
        class << self
          include A::Helper    
    
          def grovel(x)
            return helper(x) + 12
          end
        end
      end
    
    
    end
    
    puts A::C1.grovel(7)
    puts A::C2.grovel(25)
    

    You create a submodule of A, and include it in your classes as a Mixin. That way only these classes can access the method.

    You can see it working in http://rubyfiddle.com/riddles/31313

Leave a Reply

Your email address will not be published. Required fields are marked *

You can use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>