Forum: Ruby Why is my method not found? (NoMethodError)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
1685f91cc5853eb465ca50aa68b91421?d=identicon&s=25 anansi (Guest)
on 2007-05-07 16:55
(Received via mailing list)
Hi,
I have written a small tcp scanner procedural and wanted to change it to
OOP but something went wrong. Until this line everything works fine:

            my_scanner.scanning(hosts,ports)

but here I always get:
           test.rb:95: private method `scanning' called for
#<Scanner:0xb7c9c428> (NoMethodError)

but why? my_scanner is from the Scanner class which owns the method
scanning?!? Do I get something wrong?

here's my code:

#!/usr/bin/ruby -w

require 'socket'
require 'timeout'


  class Scanner


     def initialize
        @hosts,@ports = Array($*)
     end



     def portarrange
        case @ports
          when /^.+[..]/                                        # for
ranges (75..123)
             @ports = @ports.split("..")
             @ports = @ports[0].to_i..@ports[1].to_i
          when /^.+[,]/                                         # for
multiple ports (34,345,213)
             @ports = @ports.split(",")
          else
             @ports = Array(@ports)                             # for
one single port (21)
          end
     end



     def hostarrange
        case @hosts
          when /^.+[,]/                                        # for
multiple IP's/hosts (81.95.1.40,64.111.124.251,www.cnn.com)
             @hosts = @hosts.split(",")
          else
             @hosts = Array(@hosts)                             # for
one single port (81.95.1.40)
          end
     end


    def output(state,port)
       printed = false
       portsfile = File.new("ports", "r")
       scanpat = "^.+ #{port}/tcp"
       portsfile.each_line do |line|
                    if line =~ Regexp.new(scanpat)
                      puts "#{state}    : #{line}"
                      printed = true
                    end
                    puts "#{state}    : #{port}" if printed == false
end
       ensure
       portsfile.close
       end
    end

    def scanning(hosts,ports)
           hosts.each do |host|
            begin
              puts "scanning #{host}:"
              ports.each do |port|
                begin
                    Timeout::timeout(10){TCPSocket.new(host, port)}    #
set timeout here
                       rescue Timeout::Error
                          output("filtered",port)
                       rescue
                          output("closed",port)
                       else
                          output("open",port)
                end   end
            end
    end
end


#####################  code  start  #####################

puts "no arguments past,correct usage:\nruby #{$0} [hosts] [ports]\n" if
!ARGV[1]

my_scanner = Scanner.new

hosts = my_scanner.hostarrange
ports = my_scanner.portarrange
=begin
puts "debugging: "
puts hosts
puts ports
# everything alright until here
=end
my_scanner.scanning(hosts,ports)

#####################      eof      #####################


--
greets

                            (
                            )
                         (
                  /\  .-"""-.  /\
                 //\\/  ,,,  \//\\
                 |/\| ,;;;;;, |/\|
                 //\\\;-"""-;///\\
                //  \/   .   \/  \\
               (| ,-_| \ | / |_-, |)
                 //`__\.-.-./__`\\
                // /.-(() ())-.\ \\
               (\ |)   '---'   (| /)
                ` (|           |) `
          jgs     \)           (/


one must still have chaos in oneself to be able to give birth to a
dancing star
7a0d8ff2f48c5602cd8db1d115af0168?d=identicon&s=25 Evan Light (Guest)
on 2007-05-07 17:16
(Received via mailing list)
Your problem is that there is way too much nesting within your
methods.  You lost track of which "end" maps to which "do" and "begin"
in numerous places.  As a general rule, if you're nesting more than
two levels deep within a method, you just made your method a lot more
difficult to maintain.  The below version fixes your nesting issues
(but does not correct them for maintainability).

require 'socket'
require 'timeout'

  class Scanner

     def initialize
        @hosts,@ports = Array($*)
     end

     def portarrange
        case @ports
          when /^.+[..]/
             @ports = @ports.split("..")
             @ports = @ports[0].to_i..@ports[1].to_i
          when /^.+[,]/
             @ports = @ports.split(",")
          else
             @ports = Array(@ports)
          end
     end

     def hostarrange
        case @hosts
          when /^.+[,]/
             @hosts = @hosts.split(",")
          else
             @hosts = Array(@hosts)
          end
     end

    def output(state,port)
       printed = false
       portsfile = File.new("ports", "r")
       scanpat = "^.+ #{port}/tcp"
       begin
         portsfile.each_line do |line|
           if line =~ Regexp.new(scanpat)
             puts "#{state}    : #{line}"
             printed = true
           end
           puts "#{state}    : #{port}" if printed == false
         end
       ensure
       portsfile.close
       end
    end

    def scanning(hosts,ports)
      hosts.each do |host|
        begin
          puts "scanning #{host}:"
          ports.each do |port|
            begin
              Timeout::timeout(10){TCPSocket.new(host, port)}
            rescue Timeout::Error
              output("filtered",port)
            rescue
              output("closed",port)
            else
              output("open",port)
            end
          end
        end
      end
    end
end

#####################  code  start  #####################

puts "no arguments past,correct usage:\nruby #{$0} [hosts] [ports]\n"
if
!ARGV[1]

my_scanner = Scanner.new

hosts = my_scanner.hostarrange
ports = my_scanner.portarrange
=begin
puts "debugging: "
puts hosts
puts ports
# everything alright until here
=end
my_scanner.scanning(hosts,ports)

#####################      eof      #####################
7a0d8ff2f48c5602cd8db1d115af0168?d=identicon&s=25 Evan Light (Guest)
on 2007-05-07 17:26
(Received via mailing list)
Sorry.  Neglected to provide the literal answer to your question.
Because of the incorrect placement of "end"s, your definition of
"scanning" actually occurred within another one of your method
definitions.  I hadn't tried that before but, unsurprisingly, it has
the net effect of making your "method within a method" private.
1685f91cc5853eb465ca50aa68b91421?d=identicon&s=25 anansi (Guest)
on 2007-05-07 17:35
(Received via mailing list)
Evan Light wrote:
> Sorry.  Neglected to provide the literal answer to your question.
> Because of the incorrect placement of "end"s, your definition of
> "scanning" actually occurred within another one of your method
> definitions.  I hadn't tried that before but, unsurprisingly, it has
> the net effect of making your "method within a method" private.
>

hi,
many thanks !! now I could fix it with your help (there was a further
"end"-mistake in the output routine..) but do you know any tricks or
meassures to avoid these deep nestings while coding or keep track of the
begins and ends of ones code?

--
greets

                            (
                            )
                         (
                  /\  .-"""-.  /\
                 //\\/  ,,,  \//\\
                 |/\| ,;;;;;, |/\|
                 //\\\;-"""-;///\\
                //  \/   .   \/  \\
               (| ,-_| \ | / |_-, |)
                 //`__\.-.-./__`\\
                // /.-(() ())-.\ \\
               (\ |)   '---'   (| /)
                ` (|           |) `
          jgs     \)           (/


one must still have chaos in oneself to be able to give birth to a
dancing star
83ca41657a99b65d99889abe712ba5e2?d=identicon&s=25 Jason Roelofs (Guest)
on 2007-05-07 18:13
(Received via mailing list)
You are using an editor with proper syntax highlighting right?

With vim, my method, module, and class begin/do/end keywords are purple,
while all other block keywords are yellow. Makes it very easy to see if
I
missed a method end or a block end.

Jason
1c0cd550766a3ee3e4a9c495926e4603?d=identicon&s=25 John Joyce (Guest)
on 2007-05-07 19:05
(Received via mailing list)
>
> hi,
> many thanks !! now I could fix it with your help (there was a
> further "end"-mistake in the output routine..) but do you know any
> tricks or meassures to avoid these deep nestings while coding or
> keep track of the begins and ends of ones code?
>
Code folding is one way. In TextMate for example, it is easy to see
if you put end in enough times.
One other thing is to put a comment after an 'end' to tell you what
it is ending.

C-like languages can be just as much trouble with closing braces.
5625fece788f2e5f37ead8a8a094638a?d=identicon&s=25 zswu (Guest)
on 2007-05-08 02:57
(Received via mailing list)
It's a good habit that just writed *end* after you had writen "class,
def, if, do, e.t.c" before code the segment.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-05-08 03:01
(Received via mailing list)
On May 7, 2007, at 7:56 PM, zswu wrote:

> It's a good habit that just writed *end* after you had writen "class,
> def, if, do, e.t.c" before code the segment.

I feel it's a much better idea to use an editor that handles that
busy work for you.  It just drops the error count too much not to be
worth it.

James Edward Gray II
5625fece788f2e5f37ead8a8a094638a?d=identicon&s=25 zswu (Guest)
on 2007-05-08 03:18
(Received via mailing list)
Certainly, this is a good idea, though i dont use this kind of
editor.Because i want more controlling to my code, and this method
make me feelling better.It is just a personal habit, not anything
else.Everyone has own good play.
7a0d8ff2f48c5602cd8db1d115af0168?d=identicon&s=25 Evan Light (Guest)
on 2007-05-08 07:25
(Received via mailing list)
On May 7, 11:31 am, anansi <kaz...@oleco.net> wrote:
> meassures to avoid these deep nestings while coding or keep track of the
> begins and ends of ones code?

The first question that I ask myself when I start to nest deeploy is
"should I be factoring some of this nested code into additional
methods".  If even for the sake of my own sanity, the answer is
usually "yes". ;-)
This topic is locked and can not be replied to.