Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

What is this Moose mojo?

by sundialsvc4 (Abbot)
on Feb 04, 2009 at 22:14 UTC ( [id://741436]=perlquestion: print w/replies, xml ) Need Help??

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

In HTML::FormHandler::Field I see this magic:

has 'fif' => ( is => 'rw', reader => '_fif' ); sub fif { my $self = shift; return $self->_fif unless $self->password; }

And... “I don't get it.” There is:

  1. A property whose name exactly-matches the name of a subroutine. (Why isn't that a conflict?)
  2. No apparent definition of “_fif(Anywhere! Verily, the phrase appears but twice in all the world, and both of them are right here!)
  3. A reference to _fif within the unexplained-subroutine!

Oh fellow Monks, my head doth ache at this wonderous sight! Prithee, what doth it mean? I am but a wayfaring stranger...

Replies are listed 'Best First'.
Re: What is this Moose mojo?
by zwon (Abbot) on Feb 04, 2009 at 22:27 UTC
    has 'fif' => ( is => 'rw', reader => '_fif' );

    this will create read accessor with name _fif instead of usual fif, so that's where _fif from and that's why no names conflict.

      All right then... (damn! that was quick!) :-D ... we still seem to have an attribute and a sub that are both named “fif.”

      Why is there not a conflict with regard to the without an underscore name? Don't we now have a method-name and an attribute-name that are identical? If I now say “$foo->fif,” (no underscore...) what happens ... and why?

      Does the author ... intend ... to first set-up the has declaration, i.e. “just to create the accessor,” and then to immediately supersede it with his own sub? (Blink...) If so, why??

        Does the author ... intend ... to first set-up the has declaration, i.e. “just to create the accessor,” and then to immediately supersede it with his own sub? (Blink...) If so, why??

        It seems author doesn't want you be able to read password fields using $foo->fif (but you still can read them using $foo->_fif).

        Update: Uhm... if it's boolean, then why it's called password?

        =head2 password This is a boolean flag to prevent the field from being returned in the C<$form->fif> and C<$field->fif> methods. =cut has 'password' => ( isa => 'Bool', is => 'rw' );

        If you say "$foo->fif", the fif method is called. The "fif" attribute is stored as "$foo->{fif}".

Re: What is this Moose mojo?
by massa (Hermit) on Feb 04, 2009 at 23:19 UTC
    When you write
    has fif => ( is => 'rw' );
    Moose creates:
    • one attribute called $self->{fif} (that you should not use anyway, encapsulation and all that)
    • one reader accessor method called $self->fif
    • one writer accessor method called $self->fif($value)
      (actually, the last two are just one method IIRC...)
    When you write
    has fif => ( is => 'rw', reader => '_fif' );
    ,Moose creates:
    • one attribute called $self->{fif} (that you should not use anyway, encapsulation and all that)
    • one reader accessor method called $self->_fif
    • one writer accessor method called $self->fif($value)
    When you subsequently write
    sub fif { ...... }
    you are creating another method, that has nothing to do with the others. But, as convention in perl is that _methods beginning with an underscore are private, people will call the $self->fif method to read the attribute so they won't see the value unless the password thing is true. Silly, not great security, but that is that.
    []s, HTH, Massa (κς,πμ,πλ)

      If so, does it work at all?

      use strict; use warnings; { package TTT; use Moose; has fif => ( is => 'rw', reader => '_fif' ); sub fif { my $self = shift; 33; } } my $m = TTT->new(); $m->fif(42); print $m->fif, "\n"; 1; __END__ 42

      Update: but s/reader/accessor/ and it would work.

      Nice explanation. Just one addition - the goal of this is that the field is not re-filled in a form that is re-displayed - that is: the user fills up a form and submits it, there is an error in his input - so the form is redisplayed with the values filled in by the user (plus the mark for the error), but the usual approach is that the password fields are not re-filled. I don't know if that is silly security - but it is rather standard procedure.
Re: What is this Moose mojo?
by pileofrogs (Priest) on Feb 04, 2009 at 22:30 UTC

    1) Perl can have a sub,scalar, list etc all with the same name. It's not a conflict.

    2 & 3) It's probably doing some autoloading. Basically, this allows it to make up new names for functions. Not-so-basically, see http://perldoc.perl.org/perlsub.html#Autoloading.

      Perl can have a sub,scalar, list etc all with the same name.

      Lists can't have names. I think you mean array.

      1) Perl can have a sub,scalar, list etc all with the same name. It's not a conflict.

      While true, this is completely unrelated because it really just relates to methods, and you can only have one method of the same name in the same package.

      2 & 3) It's probably doing some autoloading. Basically, this allows it to make up new names for functions. Not-so-basically, see http://perldoc.perl.org/perlsub.html#Autoloading.

      Moose does not and never ever will do any form of AUTOLOADING.

      -stvn
Re: What is this Moose mojo?
by stvn (Monsignor) on Feb 05, 2009 at 16:52 UTC

    Actually, there is no mojo at work here, and this is most certainly not the right way to do this. I suspect to that this feature is not well tested either, because the user defined 'fif' subroutine will never get called. It likely warrants a rt.cpan.org bug report even (although I don't know, I have never used the module in question).

    has 'fif' => ( is => 'rw', reader => '_fif' ); sub fif { my $self = shift; return $self->_fif unless $self->password; }

    What is happening here is that at compile time, the user defined method 'fif' is created and added to the package symbol table. Then in the beginning of runtime, when Moose is compiling it's code, the attribute definition creates a read/write accessor method called 'fif' and a reader method called '_fif'. The read/write accessor method actually overwrites the original user defined 'fif' method. I suspect this is not at all what was intended.

    Here is what I think the author really meant to write.

    has 'fif' => ( reader => '_fif' ); sub fif { my $self = shift; return $self->_fif unless $self->password; }

    Here the user defined 'fif' method is retained and a Moose generated reader method '_fif' is created. Now, there is no writer method available, but honestly I am not sure they ever intended to create one anyway based on what the 'fif' method does.

    -stvn
Re: What is this Moose mojo?
by sundialsvc4 (Abbot) on Feb 05, 2009 at 15:20 UTC

    “Security” is not really the issue here, as long as you understand what you are doing and test everything properly. In other words, I don't think that this implementation is flawed by any means.

    Okay, I've done some more studying-and-scratching on this one, and here is the understanding that I've come up with. Fellow Monks, please tell me if I'm right.

    1. The declaration will automagically create the appropriate accessor-routines, without me having to do anything further. In other words, “these are the names of methods that will magically appear,” not “the names of methods that you are obligated to provide.”
    2. This module-author intentionally chose a “non-standard” name for his read-accessor routine, by prefixing an underscore '_' to the name. Then, he provided what amounts to a read-accessor of his own, with the name that you would have expected. And this one calls the accessor created by the preceding declaration.
    3. There would have been a conflict had he said sub _fif, because then there would have been two subs by that name. But here, “that name's not taken,” so it's okay.

    (Blink...)   Yes?

      See id:/741465. I can't (I'm just too lazy, to install all this stuff) check, but are you sure that when you calling $field->fif the right function is invoked? It looks like a bug for me. Author should s/reader/accessor/ or just remove is property.

      zwon

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://741436]
Approved by pileofrogs
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2024-04-19 13:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found