Adding functionality to Rails
-
09-06-2019 - |
Question
I'm working on a Rails app and am looking to include some functionality from "Getting the Hostname or IP in Ruby on Rails" that I asked.
I'm having problems getting it to work. I was under the impression that I should just make a file in the lib directory, so I named it 'get_ip.rb', with the contents:
require 'socket'
module GetIP
def local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
end
I had also tried defining GetIP as a class but when I do the usual ruby script/console
, I'm not able to use the local_ip
method at all. Any ideas?
Solution
You haven't described how you're trying to use the method, so I apologize in advance if this is stuff you already know.
The methods on a module never come into use unless the module is included into a class. Instance methods on a class require there to be an instance of the class. You probably want a class method instead. And the file itself should be loaded, generally through the require statement.
If the following code is in the file getip.rb,
require 'socket'
class GetIP
def self.local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
end
Then you should be able to run it by saying,
require 'getip'
GetIP.local_ip
OTHER TIPS
require
will load a file. If that file contains any class/module definitions, then your other code will now be able to use them. If the file just contains code which is not in any modules, it will get run as if it were in the same place as your 'require' call (like PHP include)
include
is to do with modules.
It takes all the methods in the module, and adds them to your class. Like this:
class Orig
end
Orig.new.first_method # no such method
module MyModule
def first_method
end
end
class Orig
include MyModule
end
Orig.new.first_method # will now run first_method as it's been added.
There's also extend
which works like include does, but instead of adding the methods as instance methods, adds them as class methods, like this:
Note above, how when I wanted to access first_method, I created a new object of Orig
class. That's what I mean by instance method.
class SecondClass
extend MyModule
end
SecondClass.first_method # will call first_method
Note that in this example I'm not making any new objects, just calling the method directly on the class, as if it had been defined as self.first_method
all along.
So there you go :-)
require
and include
are two different things.
require
is to strictly load a file once from a load path. The loadpath is a string and this is the key used to determine if the file has already been loaded.
include
is used to "mix-in" modules into other classes. include
is called on a module and the module methods are included as instance methods on the class.
module MixInMethods
def mixed_in_method
"I'm a part of #{self.class}"
end
end
class SampleClass
include MixInMethods
end
mixin_class = SampleClass.new
puts my_class.mixed_in_method # >> I'm a part of SampleClass
But many times the module you want to mix in is not in the same file as the target class. So you do a require 'module_file_name'
and then inside the class you do an include module
.