Method definitions are code just like any other code. They can appear in methods just like any other code. And just like any other code, they will be executed every time the method runs.
So, this
class Foo
def foo
def bar
end
end
end
is not a nested method, but simply a method that defines a method. It is easy to see that this is not a nested method, by simply calling it twice, paying attention to the warnings generated and inspecting the defined methods of the surrounding module:
foo = Foo.new
Foo.public_instance_methods(false)
#=> [:foo]
foo.foo
Foo.public_instance_methods(false)
#=> [:foo, :bar]
foo.foo
# (irb):3: warning: method redefined; discarding old bar
# (irb):3: warning: previous definition of bar was here
As you can see, bar
is not nested inside foo
, instead it is defined besides foo
in class Foo
. It is only defined after foo
has run, and it gets re-defined every time foo
runs.
Your example is a bit different, of course, since it doesn't keep overwriting the method in the same class, instead it defines it in a different class every time it is called.
Note that there are plans of forbidding this kind of usage, see Feature #11665: Support nested functions for better code organization.
But what DO you call it?
It's a method that defines a method.
And is there a better way to achieve the same functionality?
It's kinda hard to tell what exactly it is you are trying to achieve.
You could create a module
with your method and extend
all the objects with it. That would be the closest analog.
Other solutions would require a larger restructuring of your code, e.g. using the Decorator Design Pattern or, in your specific Rails use case, a Presenter.