neilwatson has asked for the wisdom of the Perl Monks concerning the following question:

I've been pooring over nodes here as well as the Camel book. Try as I might I just don't understand how one creates and references modules.

I present to you a basic concept of what I would like:

# this is properly placed where perl can find it use Mymodules::Auth; use strict; use warnings; print "Username: "; my $username = STDIN; chomp $username; ReadMode('noecho'); print "Password: " my $passwd = STDIN; chomp($passwd); ReadMode('restore'); # somehow pass $username and $password to # Mymodules::Auth and the subroutine auth # this will return 0 or 1. my $auth = Mymodules::Auth->auth($username, $passwd);
The module:
package Mymodules::Auth; use strict; use warnings; sub auth { my $username = shift @_; my $passwd = shitf @_; # here I would use DBI to get the password # and username from a database . . . if ($db-passwd eq $passwd){ $auth = 1; return $auth; }else{ $auth = 0; return $auth; } } 1;

I've tried following examples but, it just does not seem clear to me how to go about this. No matter what I do, I always get an error similar to "Undefined subroutine..."

Neil Watson
watson-wilson.ca

Replies are listed 'Best First'.
Re: Building modules, my mental block
by jeffa (Bishop) on Apr 19, 2004 at 20:12 UTC

    You don't have to, but when building "Object Oriented" modules, use a constuctor:

    use strict; use warnings; my $auth = Mymodules::Auth->new(); $auth->auth('foo', 'bar'); package Mymodules::Auth; sub new { my $class = shift; my $self = {}; return bless $self, $class; } sub auth { my ($self,$user,$pass); ... }
    And chromatic is spot on ... you are not removing the package name from your method argument list.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Building modules, my mental block
by chromatic (Archbishop) on Apr 19, 2004 at 20:00 UTC

    Do you perhaps mean sub auth {?

    You probably should check that your module can compile; try $ perl -cw path/to/Mymodules/Auth.pm. Of course, I'd expect Perl to give you an error message along those lines, so I suspect you haven't posted the exact code or error output. Perhaps that would help us diagnose the trouble.

    Update: Ah, you're not shifting off the package name when you call the packaged sub as a class method!

      Ah, you're not shifting off the package name when you call the packaged sub as a class method!

      Can you explain that in simpler terms?

      Neil Watson
      watson-wilson.ca

        Sure. This call:

        my $auth = Mymodules::Auth->auth($username, $passwd);

        is a method call. See any of the Perl documentation about OO for why this is. The important thing is that it passes three arguments. The first argument is the invocant, the string Mymodules::Auth.

        The sub you're calling is not a method, in that it doesn't account for the possibility of an invocant.

        sub auth { my $username = shift @_; my $passwd = shift @_;

        $username will end up containing Mymodules::Auth, $passwd will end up containing what you passed as the username, and the password will stick around in @_.

        Instead, if you plan to call this as a class method, deal with the invocant:

        sub auth { my ($class, $username, $passwd) = @_; # ... more code here }

        Still, I can't explain why this causes the error message you kinda sorta don't really quote. You'll have to post more code and the exact error message you receive; you know the drill.

      Sorry, the lack of sub was just a typo here. The trouble still exist.

      Neil Watson
      watson-wilson.ca

Re: Building modules, my mental block
by disciple (Pilgrim) on Apr 19, 2004 at 21:35 UTC
    I believe you can leave the module as is and just call it differently as well; maybe somebody can verify this. Note: This is no longer a Class method you are calling. You are simply calling a sub routine in a different namespace. Example (notice the double colon before auth):
    my $auth = Mymodules::Auth::auth($username, $passwd);
    I didn't have time to test this code, so I don't know if it is syntactically correct.

      That is correct. You should use :: and not -> if you want to invoke a subroutine directly, and not as a class method. If you want to invoke it as a class method, you'll need to handle the extra parameter as described above

      However, I think the error you're getting is generated by the line my $username = STDIN; As written, that statement attempts to call a (nonexistent) subroutine called STDIN. What you probably meant was my $username = <STDIN>; or even  my $username = <>; which reads a line from a filehandle