Can't call method "model" on an undefined value at - perl

I have been building catalyst apps of a number of years now. This is the first time I am getting an error trying to open a view. When I call the view (there is only one view), I get the following error:
Can't call method "model" on an undefined value at....
The following snippet of code is used in Root.pm,. This is what is generating the error on the browser. Again, this is not the first time I am using this catalyst method to call a model.
my $model = $c->model( 'mypackage' );
my $result = $model->get_my_results();
The alternative is to use:
use mypackage;
my $model = 'mypackage';
my $results = $model->get_my_results();
Has any one ever encounter this before? If yes, can you tell me how you resolved it.
Thanks
EDITED
Please note, as indicated in the original post, this is a Perl Catalyst app. The $c is a Catalyst object. In the Root.pm file, $c is received as follows:
sub myform :Local {
my ($self, $c) = #_;
my $model = $c->model( 'mypackage' );
my $results = $model->get_my_results();
.
.
.
}

Typo? Did you mean $c->model in your first line?

So, I figured out the path of my evil ways. I inadvertently forgot to pass $c in the calling method. Therefore the $c in myform() had no value. Hence, it could not find the Catalyst method called "model".
sub myform :Local {
my ($self, $c) = #_;
my $model = $c->model( 'mypackage' );
my $results = $model->get_my_results();
.
.
.
}
sub someother_method :Local {
my ($self, $c) = #_;
.
.
.
my $myform_info = $self->myform($c) <---this was missing the $c
.
}

Related

What happens if you call shift inside an anonymous sub?

First off, apologies if this question is ill-posed; I don't actually know a heck of a lot of perl.
I'm trying to debug some existing code that is supposed to send grades from our online homework system called WeBWorK to an LMS. I'm running into a weird error where I think something isn't getting initialized right, or perhaps isn't the right class. I suspect that the problem might be here:
sub go {
my $self = shift;
my $r = $self->r;
my $ce = $r->ce;
# If grades are begin passed back to the lti then we peroidically
# update all of the grades because things can get out of sync if
# instructors add or modify sets.
if ($ce->{LTIGradeMode}) {
my $grader = WeBWorK::Authen::LTIAdvanced::SubmitGrade->new($r);
my $post_connection_action = sub {
my $grader = shift;
# catch exceptions generated during the sending process
my $result_message = eval { $grader->mass_update() };
if ($#) {
# add the die message to the result message
$result_message .= "An error occurred while trying to update grades via LTI.\n"
. "The error message is:\n\n$#\n\n";
# and also write it to the apache log
$r->log->error("An error occurred while trying to update grades via LTI: $#\n");
}
};
if (MP2) {
$r->connection->pool->cleanup_register($post_connection_action, $grader);
} else {
$r->post_connection($post_connection_action, $grader);
}
}
... # a bunch of other stuff happens in the "go" sub
I kinda suspect that the issue is with the $grader variable; in particular, I don't know what my $grader = shift; does inside an anonymous sub. Like, if the sub had a name, it would be more clear that shift is giving the first argument passed to the sub. But since it's anonymous, I don't know what it thinks its arguments are.
Further, I'm not really sure why that line is needed at all. Like, from my googling, I'm given to understand that the point of an anonymous sub is to keep all the variables from the surrounding environment in scope. So why do we need to redefine $grader inside the anonymous sub in the first place?
Thanks for helping a perl noob out! :)
There's nothing special about anon subs in this regard.
my $cr = sub {
my $arg = shift;
say $arg;
};
$cr->("foo"); # Prints "foo"
$cr->("bar"); # Prints "bar"
In your case, you pass $post_connection_action and $grader to cleanup_register or post_connection with the expectation that it will result in a call to &$post_connection_action with $grader as its first argument. Whether the expectation is correct or not depends on the implementation of cleanup_register and post_connection, of which I know nothing.
Note that another solution presents itself here. Subs have access to the lexicals that were in scope when the sub operator was evaluated.
my $prefix = "> ";
my $cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
$cr->("foo"); # Prints "> foo"
The above is true even if captured lexicals would otherwise no longer exist by the time the sub is called.
my $cr;
{
my $prefix = "> ";
$cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
} # $prefix would normally stop existing here.
$cr->("foo"); # Prints "> foo"
That means you don't need to pass $grader as an argument. It can simply be captured. Just leave out my $grader = shift; (and don't pass $grader to
cleanup_register or post_connection).

Why am I getting the error 'Can't call method "submitted" without a package or object reference' when generating a form in Catalyst?

I'm using the following code to generate a simple form with Catalyst:
sub edit : Local {
my ($self, $c) = #_;
my $form = $self->formbuilder;
if ($form->submitted && $form->validate) {
$c->stash->{message} = 'Thanks for submitting the form!';
}
}
However, when I run it I get this error message:
Caught exception in AddressBook::Controller::Person->edit "Can't call method "submitted" without a package or object reference at /Users/me/Docs/workspace/MyAddressBook/AddressBook/script/../lib/AddressBook/Controller/Person.pm line 58."
Any ideas on what is causing this?
According to the fine manual, the attribute :Form is part of what triggers the form creation, e.g.:
sub edit : Local Form {
my ( $self, $c, #args ) = #_;
...
I'd say without that, it's not getting configured, and hence does not have a submitted method.

Strict vs non-strict: Which instance of a named variable gets used?

I am trying to find the problem and propose a solution for the following Perl code.
A file without strict nor warnings on it has a function that uses a $variable without declaring it. So that variable is global to the file and the changes for that variable in this specific function are used outside of it (since it is global for the file).
Due to a recent update, this old_file now requires a modified version of itself (new_file) in which the same function is defined. But this new version has strict and warnings, so the same variable is defined, but this time as 'my' in the new function, and is returned in the end.
The tricky thing is that the code in the old_file did not change so it still expects the variable to be changed as its own global variable.
Since I don't know Perl well enough to be able to determine which version of this function is used (and since I can't test it, due to IT restrictions) I need an explanation of the behavior, possibly a link to a good paper about that topic.
Code: (I think the problem is in the variable LISTEREPONSE from the function start_handler.)
old_file:
use XML::Parser;
my $parser = new XML::Parser( ErrorContext => 2 );
$parser->setHandlers(
Start => \&start_handler,
End => \&end_handler,
Char => \&char_handler
);
$parser->parse(<$remote>);
close $remote;
...
sub start_handler {
my $expat = shift;
my $element = shift;
print;
while (#_) {
my $att = shift;
my $val = shift;
$LISTEREPONSE .= "$att=$val&";
}
}
new_file:
sub start_handler {
my $expat = shift;
my $element = shift;
print;
my $LISTEREPONSE;
while (#_) {
my $att = shift;
my $val = shift;
$LISTEREPONSE .= "$att=$val&";
}
return $LISTEREPONSE;
}
In strict mode, if you need $LISTEREPONSE become a global variable in package(file) scope.
Just declare (my $LISTEREPONSE;) in the beginning of file (after use).
In second case, $LISTEREPONSE is declare in sub, it's lexical scope and only available in sub.
my $LISTEREPONSE;
# ...
sub some_sub {
$LISTEREPONSE .= $some_stuff;
}

Perl difficulty passing values to function

Cannot understand why the returned values from the function login bellow do not correspond to what is passed to it.
The following is a snippet of my code
package This_package;
.......
# returned from function that parses post data ($reqparam)
my $thisuser = $$reqparam{"username"};
# escape '#', username is an email
$thisuser =~ s/#/\#/;
my $thisuser_pass = $$reqparam{'password'};
print $thisuser; # ok
print $thisuser_pass; # ok
my $obj = new users;
my $valid_user = $obj->login($thisuser, $thisuser_pass);
.......
package Another_package;
sub new {
my ($class) = #_;
my $self = {
_login => undef,
_create_user => undef,
....
};
bless $self, $class;
return $self;
}
sub login ($$){
my ($user, $pass) = #_;
# some processing
.....
return $user; # prints users=HASH(...)
# return $pass; # prints the value of $user (the actual value)
# instead of the value of $pass
}
While trying to learn perl by converting some code from php into perl.
I have run into this problem, I have tried a few alternatives but obviously there is something I am not getting!
When you call a function like
my $valid_user = $obj->login($thisuser, $thisuser_pass);
The first parameter is this usually done as
sub login
{
my ( $self , $user , $password ) = #_;
}
You are missing $self
Because you are missing $self you user is actually the object and your password is actually the user.
If you are coming from another objected oriented language like C++ , Java or C#, this is a perl gotcha (no pun intended :)) . Another one is that even from an object method if you want to invoke another member method you have to use self like
$self->callAnotherObject( $user );
Simply calling wont do
callAnotherObject( $user );
Also I see that you are using function prototypes, It may not work as you intend it to be.
When you use object-oriented syntax ($obj->login($thisuser, $thisuser_pass)) to call a subroutine, the first argument will be the object itself. You should say, and you will typically see object-oriented modules use syntax like:
sub login {
my ($self, $user, $pass) = #_;
...
}
Incidentally, you shouldn't use prototypes ( ($$) ) without a good reason. Prototypes in Perl are not used in the same way they are in other languages, and in any case the prototype is ignored when you call a subroutine with indirect syntax (luckily, in your case, since you are actually calling it with 3 arguments).
You even watch Mythbusters?
Although you see Adam and Jamie do really, really dangerous stuff, they warn you at the beginning of every program, "Don't do this at home." Think of Perl prototypes in the same way. If you use them, there's a good likelihood you'll get badly burned.
Okay, now who is calling your login function? Or, maybe better, how is it called?
If I use your Perl module, do I call your login subroutine from my main program like this?
my $package_obj = Another_package->new;
$package_obj->login($user, $password);
Or, is this some subroutine that you use in your package for your convenience and you use it as a simple subroutine, and not a private method like this:
package Another_package;
sub new {
...
}
sub foo {
...
my $user = login ($user, $password);
}
If you're calling your login subroutine as a simple subroutine inside your package as in the second example, everything should be fine.
However, if you're treating your login subroutine like a full fledge method (like I do in the first example), you must remember that methods pass their class object as the first parameter of the subroutine.
Thus, you'll need to do something like this:
sub login {
my $self = shift; #Pointer to the Another_package object I'm using
my $user = shift;
my $password = shift; #I just love lining things up!
$self->{USER} = $user; #Bad way of doing it.
$self->{PASSWD} = $password;
... #Some processing.
return $user;
}
Why the #Bad way of doing it comment? Because you really want to keep your internals as separate as possible. That way, if you make a change to the structure of the Another_package class, your changes are isolated in a very specific part of your code. It makes debugging much easier.
A better way of writing the login subroutine would be:
sub Login { #In standard Perl, methods are capitalized.
my $self = shift; #Pointer to Another_package object
my $user = shift; #Allow user to pass user and password in constructor
my $password = shift; #I just love lining things up!
$self->User($user); #Way better: This is a setter/getter method
$self->Password($password);
... #Some processing.
return $user;
}
In this example, I'm using setter/getter methods for setting my user name and password. This way, I don't have to worry how they're actually stored in my object.
Here's your Another_Package module using setter/getter methods. I now allow the user to pass in the user and password when they call the new constructor if they'd like.
package Another_package;
sub new {
my $class = shift;
my $user = shift;
my $password = shift;
my $self = {};
bless $self, $class;
$self->User($user);
$self->Password($password);
...
return $self;
}
sub Login {
my $self = shift;
my $user = shift;
my $pass = shift;
$self->Password($pass);
if (not defined $self->User($user)) {
croak qq(Cannot log in without a user ID);
}
...
if ($login_successful) {
return $self->User; #Or maybe a session instant
else {
return;
}
}
Notice in my new constructor subroutine I create a $self anonymous hash (my $self = {}) and I immediately bless it. Now, $self is already a package object, and I can call a bunch of setter/getter methods to set the various fields in my object. My new constructor has no idea what my actual Another_module object looks like.
In my Login method subroutine, I also use the same setter/getter methods to set user and password. Again, my Login method knows nothing on how these fields are stored in the object.
One more thing you might notice is that I'm setting a scalar called $login_successful in my Login module to see whether or not my login was successful. In Perl, it is common to return nothing if the method fails, or return something on success. This way, the user's program can test to see if the call succeeded or failed. For example, maybe if the login fails, the user might want to try some default passwords before giving up:
my $package_obj = Another_package->new($user, $password);
my $foo = $package_obj->Login;
if (not defined $foo) {
foreach my $password qw(swordfish s3x mon3y 7ucky) {
$package_obj->Password($password);
last if $foo = $package_obj->Login;
}
if (not defined $foo) {
die "I don't know the password :-(";
}
}
So, what do my setter/getter methods look like? They're actually pretty simple:
sub User {
my $self = shift;
my $user = shift;
if(defined $user) {
$self->{USER_INFO}->{USER} = $user;
}
return $self->{USER_INFO}->{USER};
}
sub Password {
my $self = shift;
my $pass = shift;
if (defined $password) {
$self->{USER_INFO}->{PASSWORD} = $pass;
}
return $self->{USER_INFO}->{PASSWORD};
}
Why do I store $user in $self->{USER_INFO}->{USER} and not $self->{USER}? No reason a at all. However, it does show that the rest of the Another_package module doesn't care where or how I store the user and password.

Pass variables around the around method modifier

Is it possible to pass variables between multiple calls to the around MethodModier? example (that doesn't work but hopefully conveys what I want to do)
sub mysub { ... };
around 'mysub' => sub {
my $orig = shift;
my $self = shift;
my $value = get_value;
$self->orig(#_);
};
around 'mysub' => sub {
my $orig = shift;
my $self = shift;
my $value = shift;
my $output
= "sometext $value"
. $self->orig(#_);
. 'someothertext $value'
;
};
I'd eventually like to have these 'arounds' placed in pluggable traits, where I won't really know which ones are loaded beforehand but the final output will be neatly formatted.
It's possible that I'm thinking about this completely wrong, so other suggestions welcome.
What you are trying to do don't have logic.
"An around modifier receives the
original method as its first argument,
then the object, and finally any
arguments passed to the method."
https://metacpan.org/pod/Moose::Manual::MethodModifiers#BEFORE-AFTER-AND-AROUND
Use an instance variable:
$self->{value} = get_value;
...
my $value = $self->{value};
(See question commments for an actual answer. I'm just reiterating it here, so I can accept an answer, thanks to:
)