0

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.

4
  • 1
    How about def self.run(memo, model_class, attribute)? Commented Jun 29, 2015 at 12:03
  • Indeed. But since run is nested to self.split, why do I have to add that self also? Commented Jun 29, 2015 at 12:12
  • What is the purpose of this "nested" run method? Commented Jun 29, 2015 at 13:47
  • It is a recursive method which is triggered inside self.split. I have it mainly because I don't want to call self.split with fixed attributes, such as the []. Commented Jun 29, 2015 at 13:51

3 Answers 3

2

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 
Sign up to request clarification or add additional context in comments.

Comments

1

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.

1 Comment

Just one side note: how can I call the lambda from within itself?
1

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.

1 Comment

Maybe I asked it wrong. I don't want to call run from the outside, it's called just from within self.split. The reason I made it is explained in one of my comments from above.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.