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

Dearest wise monks

I am just starting with oo perl, read your excellent introductions on referencing, but still there's not enough light coming out of my brain :-)

I am populating an object with the attributes 'head', 'opinion', 'result' like this:

my $item = Item->new("something","another thing","the essence");

When I dump the object (with Data::Dumper) I get:

$VAR1 = bless( { 'head' => 'something', 'opinion' => 'another thing', 'result' => 'the essence' }, 'Item' );

How can I get the whole contents of $item (all between the curly brackets)? I know how to get the single elements... but not the whole object.

The aim is to index it with elasticsearch:

$e->index( index => $index, type => $type, id => $id, body => { head => $head, opinion => $opinion, result => $result, } );

and I want to replace the "body" with my item

Thanks a lot in advance for any enlightenment!

MCS

Replies are listed 'Best First'.
Re: beginner's question regarding objects
by choroba (Cardinal) on Mar 28, 2015 at 12:46 UTC
    How the internal structure of the object is organised shouldn't influence how it's indexed. If you later changed the object to
    bless $class, [ @_ ];

    you still want to index it the same way. So, either use the individual accessors:

    $e->index( index => $index, type => $type, id => $id, body => { head => $object->head, opinion => $object->opinion, result => $object->result, }, );

    or, create a method for the object to dump a structure to index:

    sub hashify { my $self = shift; return { %$self } }

    which you can later (after converting to the array implementation) change to

    my @attributes = qw( head opinion result ); sub hashify { my $self = shift; return { map { $attributes[$_] => $self->[$_] } 0 .. $#$self } }

    Update: Note that hashify creates a shallow copy, i.e. it doesn't clone nested references.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Thanks a lot for this explanation! I forgot that i could build a method for this into my model...

      As my object can get lots of accessors I was looking for a lazy - sorry, I ment efficient - way. Your "hashify" is exactly what I was looking for.

      Happy coding weekend

      MCS
Re: beginner's question regarding objects
by roboticus (Chancellor) on Mar 28, 2015 at 13:42 UTC

    McSvenster:

    Since your object is basically the hash you want with a footnote (the class it's blessed into), you can send the data to elasticsearch just like you'd do with a standard hash. There are a couple of caveats, though:

    First: if the elasticsearch API wants a hash and tries to verify that it's a hash with ref, then it may complain because your object isn't just a hash. Second, if the elasticsearch function(s) twiddle the hash, your object will be similarly twiddled. Finally, if the elasticsearch hangs on to the reference, it may bonk your object at some point in the future (alternatively, if you change your object, then elasticsearch could get confused by the change). So if the API is going to play nice, you can simply pass it your object, but if you have any doubts, you can just put in a copy. Here's a quickie example to show what I mean:

    $ cat flog.pl #!/usr/bin/env perl use strict; use warnings; my $o = bless {a=>1,b=>2,c=>3}, 'Flog'; my $j = { J => { %$o }, # Make a copy of the object K => $o # or just pass it in }; print "Before:\n"; dumpit($j); $j->{J}{a}=7; $j->{K}{b}=8; $o->{c}=9; print "After:\n"; dumpit($j); sub dumpit { my $t = shift; for my $k ('a' .. 'c') { print "$k : $t->{J}{$k} : $t->{K}{$k} : $o->{$k}\n"; } } Roboticus@Waubli ~ $ perl flog.pl Before: a : 1 : 1 : 1 b : 2 : 2 : 2 c : 3 : 3 : 3 After: a : 7 : 1 : 1 b : 2 : 8 : 8 c : 3 : 9 : 9

    In general, I'd suggest sending in a copy unless you *want* the object to be passed around. I mention elasticsearch only because you did. I don't know a thing about it, so I don't know how its API is going to treat your object.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: beginner's question regarding objects
by CountZero (Bishop) on Mar 28, 2015 at 20:37 UTC
    The basic principle of using objects is that the internal representation of the object is unimportant and that you only access the internal data through methods. Never ever should you rely directly on the internal representation of your object.

    The best solution for your task is to write a method for your object that will output its internal data as a hash-reference which you can then pass to the "body" key in the index metod of your elasticsearch object. Take care however that you do not pass a direct reference to the internal data itself but rather to a copy of the data!

    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

    My blog: Imperial Deltronics