views:

319

answers:

5

I'm working on a Rails app and am looking to include some functionality from an earlier question I asked here. However, 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?

+4  A: 

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
Curt Hagenlocher
A: 

Right on Mike! I was using require GetIP to no avail. Much thanks! Oddly enough, his post is no longer here, but he said:

include GetIP
local_ip

@Curt: Thanks, that worked as well! For future reference, what's the difference between 'include' and 'require'? I've seen some explanations before but none that really did a decent job of explaining it.

@Orion: Thanks for the great explanation, it definitely cleared things up!

Chris Bunch
+1  A: 

Oh, I deleted my answer because Curt's is much better. :)

Mike
+3  A: 

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 :-)

Orion Edwards
A: 

Require and include are 2 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 a include .

TonyLa