Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Moose object construction

by saintex (Scribe)
on Feb 09, 2011 at 15:44 UTC ( [id://887227]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,
I would like to set the accessors values of my class using an XML file.

I would like to build my class using a constructor that read an XML file and set the values.

Also, outside the constructor that values must be immutable.

So I have:

package NavigationRules; our $VERSION=0.01; use Moose; use XML::Simple; use FindBin qw($Bin); use lib ("$Bin/classes"); has 'visitors' => (is=>'ro',isa=>'Int',required=>1,default=>1); #has 'numVisits' => (is=>'ro',isa=>'Int',default=>1); sub BUILD { my $self=shift; my $rules= XMLin("$Bin/conf/navigation_rules.xml",NormaliseSpace=> +2); $self->visitors=$rules->{navigation}->{visitors}; # $self->numVisits=$rules->{navigation}->{numVisits}; } __PACKAGE__->meta->make_immutable; 1;


But in this way, I have this error:

Can't modify non-lvalue subroutine call at /home/wolf/Scrivania/naviga +tor/classes/NavigationRules.pm line 29.


That is beacause the BUILD method (constructor) tryed to modify an accesor method.

So I tried with:

has 'visitors' => (is=>'ro',isa=>'Int',writer=>'BUILD',required=>1);
But without success:

You are overwriting a locally defined method (BUILD) with an accessor +at /usr/local/lib/perl/5.10.0/Moose/Meta/Attribute.pm line 663


(I don't want to use a builder method for each accessor, beacause I would like read the XML file only one time).

So my question is:
how can I define an accessor value inside a constructor without that error?

Thank you in advance for your answers.

Replies are listed 'Best First'.
Re: Moose object construction
by CountZero (Bishop) on Feb 09, 2011 at 17:34 UTC
    Did you have a look at MooseX::ConfigFromFile? You will have to implement the get_config_from_file method yourself, but getting data out of an XML-file should be easy.

    Update: Even easier, MooseX::SimpleConfig uses Config::Any to turn your config file into Moose objects.

    And as you know, Config::Any uses XML::Simple to read xml-based config-files.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Moose object construction
by thargas (Deacon) on Feb 09, 2011 at 16:31 UTC
    Instead of $self->visitors=$rules->{navigation}->{visitors}; have you tried $self->visitors($rules->{navigation}->{visitors}); ? Moose doesn't go as far as making the accessors into lvalue subs.
      Hello, just tried:
      $self->visitors($rules->{navigation}->{visitors});
      but I have:
      Cannot assign a value to a read-only accessor at ...
      So that doesn't work.

        What you want to do is change your visitor attribute to be something like:

        has 'visitors' => ( is => 'ro', writer => '_set_visitors', init_arg => undef, );
        Then inside your BUILD method, you will want to do:
        $self->_set_visitors( ... );
        The init_arg being set to "undef" will ensure that no one can do:
        MyClass->new( visitors => ... )
        But all this said, you should really spend some time reading the Moose::Manual. Several of the mistakes you have made seem to be caused by the fact you are guessing and/or making assumptions of your own about how Moose works, rather then actually taking the time to learn how it actually works. You also might find some of the presentations on http://moose.perl.org helpful as well, there are several excellent introductory ones from recent conferences.

        You really too should give a look to MooseX::SimpleConfig as it solves this problem for you and the code has been battle tested already.

        -stvn

        Sorry about that. You can work around that somewhat by making the attribute rw, but with an internal writer, say _set_visitors(), so you can set the visitors attribute from within your code, but visitors() can't be used to set it.

        It's not perfect, but the only way around it that I can see would be to dynamically make the attribute rw, set the value and then make it ro, which isn't pretty. I'm assuming that can be done, though I've never tried.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-04-19 06:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found