Why can't Ruby find a method declared right above? - ruby

I have a simple file called helper.rb that looks like this:
module MyHelper
def initialize_helper
puts "Initialized"
end
initialize_helper()
end
And another simple file like this:
require_relative 'helper.rb'
include MyHelper
puts "Done"
But when I run this second file, it results in this error:
helper.rb:6:in `<module:MyHelper>': undefined method `initialize_helper' for MyHelper:Module (NoMethodError)
Why can't Ruby find this initializeHelper method defined directly above where I'm calling it???

Try
def self.initialize_helper
puts "Initialized"
end
Without the self., you're declaring an instance method intended to be called on objects, not the module itself. So, for instance, your original code is intended to be used like
module MyHelper
def initialize_helper
puts "Initialized"
end
end
class Foo
include MyHelper
end
Foo.new.initialize_helper
But if you want to call it on the module, you need to have self. in front of it to make it a method on the module itself.

Related

NoMethodError: undefined method `meow?' for # - ruby mixin failing?

I'm playing with some of the very basics of ruby mixins, and for some reason can't access behavior from my module.
Running this on Ruby Fiddle:
module Cats
MEOW = "meow meow meow"
def Cats.meow?
return Cats::MEOW
end
end
class Example
include Cats
def sample
return "it's a sample"
end
end
e = Example.new
puts e.sample
puts e.meow?
This keeps returning NoMethodError: undefined method 'meow?' for #
My understanding of how mixins should work from tutorialspoint makes me feel like I should be able to validly call e.meow?, and get back the same result I would get from calling Cats.meow?.
Here's the code in RubyFiddle.
Incredibly basic, but any ideas where I'm falling down here?
As it turns out, I was being overly specific when defining Cats.meow?. If you want to use a module as a mixin you'll want to define your methods more generally, not with respect to their specific module namespace.
So instead of
def Cats.meow?
...
end
it should have been
def meow?
...
end
This lets you call e.meow?, since the method definition no longer limits it just to the Cats namespace.
Whoops.
As a general rule to using include and extend in Ruby:
If you want to use your module as a namespace
module Outer
module Inner
def self.my_method
"namespaced method!"
end
end
end
You use it like this Outer::Inner::my_method or Outer::Inner.my_method.
And if you want to use the module as a mixin:
# In some cases it makes sense to use names ending in -able, since it expreses
# what kind of messages you can send to an instance or class that mixes
# this module in.
# Like Devise's Recoverable module: https://github.com/plataformatec/devise/blob/f39c6fd92774cb66f96f546d8d5e8281542b4e78/lib/devise/models/recoverable.rb#L24
module Fooable
def foo
"#{self} has been foo'ed!"
end
end
Then you can include it (instances of Something obtain #foo):
class Something
include Fooable # Now Something.new can receive the #foo message.
end
Something.new.foo
=> "#<Something:0x0055c2dc104650> has been foo'ed!"
Or you can extend it (Something itself obtains #foo as a class message):
class Something
extend Fooable # Now Something can receive the #foo message.
end
Something.foo
=> "Something has been foo'ed!"

Meaning of Syntax for Ruby Module

I've been going through some tutorials to find this information, but haven't seen anything that directly addresses it.
I've seen several times on modules the following syntax:
module MyModule
def run()
puts "running"
end
end
I've also seen syntax that looks like this:
module MyModule
def MyModule.run()
puts "running"
end
end
What's the advantage to including the module name before the method and vice versa?
module MyModule
def MyModule.run()
puts "running"
end
end
is exactly the same as:
module MyModule
def self.run()
puts "running"
end
end
Usually def self.run is used, because it's better when you have to change the module name and it's more idiomatic. I don't see any advantages in writing def MyModule.run.
This has nothing to do with modules. This is just normal method definition syntax.
The syntax for a method definition in Ruby is
def <target>.<selector>(<parameters>)
# …
end
For example:
def foo.bar(baz)
end
This will define a method named bar on the object referenced by foo (more precisely, in the singleton class of the object referenced by foo), with a single mandatory positional parameter whose binding is named baz.
Like with message sends, you can leave out the target, and Ruby will use an implicit default. In a message send, the implicit default is self, with a method definition, the default is the so-called default definee, which is usually the closest lexically enclosing module definition body.
So,
def MyModule.run
means "define a method named run on the object MyModule (or more precisely in the singleton class of the object MyModule)", whereas
def run
means "define a method named run in the default definee", i.e. the closest lexically enclosing module definition body, which in this case is MyModule.
The second version defines run as an instance method of MyModule, the first version defines run as an instance method of the singleton class of MyModule, which we sometimes call a "module method" or "module function".
Note that the first version is usually more idiomatically written as
def self.run
This is about using a module as a static namespace vs using a module as a mixin. Have a look at the following code (with output in comments):
module MyModule
def MyModule.run()
puts "#{self}: running"
end
def run()
puts "#{self}: running"
end
end
class Foo
include MyModule
end
MyModule.run #MyModule: running
foo = Foo.new
foo.run #<Foo:0x007f9b269bf028>: running
In the first usage, the module is basically just acting as a namespace to which you attach a method.
In the second, the module is mixed in to the class Foo. This means that it acts as if the run method was defined within the foo class in the first place; you could, if you wished, refer to instance variables #bar which aren't defined in the module, but only in the Foo class.
I guess both are same but in case when we call module method inside class then we have to give
ModuleName.method_name()
So that it can understand that this method is required for included or that particular module

NoMethodError in ruby module

module Add
def addition
sum=1+2
puts sum
end
a=Add.addition
Can anyone tell me what I'm missing and why I am getting this error->
undefined method `addition' for Add:Module (NoMethodError)
You are confusing class methods and instance methods. Your definition:
module Add
def addition
...
end
end
defines methods on instances of Add whereas you called a method on the module Add. If you want to define a class/module method, you need to define like:
module Add
def self.addition
...
end
end
If you want to be able to call it directly, define it as a directly accessible method:
def self.addition
# ...
end
Or you can always rework this using:
module Add
# ...(methods)...
extend self
end
Where that will automatically promote all mixin-type methods as being directly accessible.
You can also tag them more selectively like this:
module Add
def addition
# ...
end
module_method :addition
end
That method is then available either as Add.addition or if some other module or class calls include Add.

How can I refer to a module method without referring to the entire namespace?

I have a module defined as:
module MyApp
module Utility
def Utility.my_method
I want to use that method in several other classes. But I don't want to have to call:
MyApp::Utility.my_method
I would rather just call:
Utility.my_method
Is that reasonable? I've tried include MyApp::Utility and include MyApp to no avail.
Well, just assign any alias you want, e.g.:
ShortNameGoesHere = MyApp::Utility
ShortNameGoesHere.my_method
Here is an example of mixing in my_method to a class:
#myapp.rb
module MyApp
module Utility
def my_method
"called my_method"
end
end
end
#test.rb
require './myapp'
class MyClass
include MyApp::Utility
end
if __FILE__ == $0 then
m = MyClass.new
puts m.my_method
end
It sounds like you want to maintain the namespace of the module on the mixed-in method. I have seen attempts to do so (https://stackoverflow.com/a/7575460/149212) but it seems pretty messy.
If you need my_method to be namespaced, you could simply include a module identifier in the method name:
module MyApp
module Utility
def util_my_method
"called my_method"
end
end
end

Modules in Ruby

Please explain why self is used in def self.included (klass) below.
module A
def self.included(klass)
puts "A -> #{klass}"
puts A
puts self
end
end
class X
include A
end
By writing def self.included you are defining a method that is part of the singleton class of module A. In general, singleton methods can only be called by doing A.included() but this singleton method has a special name included that causes the Ruby interpreter to call when the module gets included in to a class.
A normal method in a module (defined with def foo) can only be called if the module gets included in to something else.
This is how you declare a module method that can be called directly. Normally methods defined within a module are only usable if another class or module includes them, like class X in this example.
module Example
def self.can_be_called
true
end
def must_be_included
true
end
end
In this case you will see these results:
Example.can_be_called
# => true
Example.must_be_included
# => NoMethodError: undefined method `must_be_included' for Example:Module
The self declared methods are not merged in to the classes or modules that include it, though. They are special-purpose that way.

Resources