Why is my method not found? (NoMethodError)

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

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 #####################

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.

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

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

···

On 5/7/07, anansi <kazaam@oleco.net> wrote:

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

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.

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". :wink:

···

On May 7, 11:31 am, anansi <kaz...@oleco.net> wrote:

EvanLightwrote:
> 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?

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

···

--
/***********************************/
    Lets go With the float....
/***********************************/

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

···

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.

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.

···

On 5/8/07, James Edward Gray II <james@grayproductions.net> wrote:

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

--
/***********************************/
    Lets go With the float....
/***********************************/