linkyndy
linkyndy

Reputation: 17900

Call a nested method in a module's method

I have the following module defined, together with a module method and a method nested inside the module's method:

module RansackHelpers
  def self.split(attribute, model_class)
    def run(memo, model_class, attribute)
      # Code
    end
    run([], model_class, attribute)
  end
end

How can I call run inside self.split? Apparently, it doesn't found the nested method.

Upvotes: 0

Views: 528

Answers (3)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230286

If you wanted to have a "local function", you can emulate it with lambdas.

module RansackHelpers
  def self.split(attribute, model_class)
    run = ->(memo, model_class, attribute) do 
      # Code
    end
    run.call([], model_class, attribute)
  end
end

From this example, it's not obvious why you'd want to do this. If it's defined and called right away, you might as well just execute the function body directly. If it's to be used from outside, you should create a normal, not nested method.

For recursive calls, this should be just the thing.

Upvotes: 1

steenslag
steenslag

Reputation: 80065

There is no such thing as a nested method in Ruby. If you call run before split you will get a NoMethod error. If you call split twice you will get a warning: "warning: method redefined; discarding old run."

You have a method split which defines another method when called.

Upvotes: 1

ifyouseewendy
ifyouseewendy

Reputation: 6674

There is a current class conception in Ruby, according to Metaprogramming Ruby 2

Wherever you are in a Ruby program, you always have a current object: self. Likewise, you always have a current class (or module). As The Ruby interpreter always keeps a reference to the current class (or module), when you define a method, that method becomes an instance method of the current class.

And it changes with the class and module keyword.

When you open a class with the class keyword (or a module with the module keyword), that class becomes the current class.

So in your case, the current class of where run method defined is still RansackHelpers, but not RansackHelpers's singleton class.

Here it works,

module RansackHelpers
  class << self
    def split(attribute, model_class)
      def run(memo, model_class, attribute)
        # Code
      end
      run([], model_class, attribute)
    end
  end
end

Upvotes: 2

Related Questions