Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I assign many Moose attributes at the same time?

I'm gradually Moose-ifying some code that reads lines from a pipe delimited, splits each and assigns adds them to a hash using a hash slice.

I've turned the hash into a Moose class but now I have no idea how to quickly assign the fields from the file to the attributes of the class (if at all).

I know I can quite easily just do:

my $line = get_line_from_file;
my @fields = split /\|/, $line;
my $record = My::Record->new;
$record->attr1($fields[0]);
...

but I was hoping for a quick one liner to assign all the attributes in one go, somewhat akin to:

my $line = get_line_from_file;
my %records;
@records{@field_names} = split /\|/, $line;

I've read about coercion but from what I can tell it's not what I'm after.

Is it possible?

Thanks

like image 211
Sparkles Avatar asked Jan 11 '10 01:01

Sparkles


3 Answers

Pass the attributes to the constructor using zip from the List::MoreUtils module:

use List::MoreUtils qw/ zip /;

my $object = My::Record->new(
  zip @field_names,
      @{[ split /\|/, get_line_from_file ]}
);
like image 122
Greg Bacon Avatar answered Oct 23 '22 01:10

Greg Bacon


I think you're on the right track with the hash slice approach. I'd do something like:

my %fields;
@fields{@field_names} = split m{\|}, $line;
my $record = My::Record->new( %fields );

You might be able to come up with a gnarly map solution to achieve the same thing, but I'd err on the side of readability here.

like image 35
friedo Avatar answered Oct 23 '22 03:10

friedo


If the object is not constructed yet, you can simply pass all the keys and values into the constructor:

my $line = get_line_from_file;
my %records;
@records{@field_names} = split /\|/, $line;
my $object = My::Record->new(%records);

or if the object is already created and you want to add some new fields:

my $line = get_line_from_file;
my %records;
@records{@field_names} = split /\|/, $line;
while (my ($key, $value) = each(%records)
{
    $object->$key($value);

    # or if you use different names for the setters than the "default":
    $object->set_value($key, $value);
}
like image 34
Ether Avatar answered Oct 23 '22 03:10

Ether