4

I'm working on a Catalyst database project and trying to do some AJAX requests via jQuery. Parameters are being sent OK, as can be seen in image 1.

List of parameters and values received in AJAX request

Notice that both "diagnosis" and "type_consents" (and their corresponding dates) are sent as an array of values (value 1, value 2, ... value n).

Now for the server side treatment, Catalyst::Request allows for easy data retrieval through $req->parameters, but it doesn't seem to be working for me.

I'm doing it like this:

my $params = $c->request->parameters; #Retrieving all parameters

my @type_consents         = $params->{type_consent};
my @date_consents         = $params->{date_consent};
my @diagnosis             = $params->{diagnosis};
my @date_diagnosis        = $params->{date_diagnosis};

Then I need to loop these arrays and make an insertion for each pair of values (diagnosis|date , consent|date). Plus, I need to store and process all transactions and execute them all at once in an eval() block, so I'm doing it like this:

my %transactions;

# Diagnosis
my $diag_index = 0;

foreach my $key ( 0 .. $#diagnosis ) {
    $transactions{diagnosis}{$diag_index} = $diagnosis_mod->new(
        {
            subject_id          => $subject_id,
            diagnosis_date      => $date_diagnosis[$key],
            diagnosis           => $diagnosis[$key],
            diagnosis_comment   => "",
            suggested_treatment => ""
        }
    );

    print STDERR "\n" . $date_diagnosis[$diag_index];
    print STDERR "\n DEBUG: $date_diagnosis[$diag_index] | $diagnosis[$diag_index] | key: $diag_index";
    print STDERR "\n DEBUG2:" . Dumper( @date_diagnosis ) . " | " . Dumper( @diagnosis );

    $diag_index++;
}

# I'm avoiding evaluating and performing the transactions so neither eval() nor database impact are shown above.

Those debugs print the following:

Debugs of array iteration

Does this suggest that my "array" is just a unidimensional variable with a string? I tried splitting it but that doesn't work either.

Community
  • 1
  • 1
Leitouran
  • 578
  • 3
  • 16

1 Answers1

1

The only values you can store in a hash are scalars. Thus, $params->{type_consent} is a scalar, not a list. However, since references to things (scalars, arrays, hashes, objects, globs, etc.) are also scalars, you can store references in a hash.

What $params->{type_consent} is, therefore, is a reference to an array, not an array or list itself.

What I think you want, then, is either to assign that to my $type_consent = $params->{type_consent}; and then use @$type_consent as your array (and thus they both point at the same array - changing something through @$type_consent changes that array in %$params), or copy the array by saying my @type_consent = @{$params->{type_consent}};.

Which one I choose to use is situational, but I tend towards the reference option if only to keep memory usage down if there is no reason to copy it.

Tanktalus
  • 21,664
  • 5
  • 41
  • 68
  • Well both did pretty good. Thanks a lot, @Tanktalus. I personally think second option is a little bit easier to read, so I'm going with that one, but both worked :) – Leitouran Jan 23 '17 at 16:29
  • I was doing some testing and it seems like this works fine ONLY when 2 or more elements are being sent. I receive this error whenever 1 element (minimum acceptable for request) is sent: `[error] Caught exception in pbitdb::Controller::Subjects->add "Can't use string ("1") as an ARRAY ref while "strict refs" in use at /home/lioneluranl/svn/pbitdb/pbitdb/script/../lib/pbitdb/Controller/Subjects.pm line 119."` ... where in this case "1" is the value sent... and the line referenced is the one where I declare the list: `my @type_consents = @{$params->{type_consent}};` Any ideas? – Leitouran Jan 24 '17 at 20:22
  • 1
    IMO, it's poor design to have dynamic types - a key that can have a scalar value *or* an array (reference) value. However, if the API you're calling is not under your control, you may have to deal with it in your code: `my @type_consent = ref $params->{type_consent} ? @{$params->{type_consent}} : $params->{type_consent};` Similar for keeping as reference: `my $tc = ref $params->{type_consent} ? $params->{type_consent} : [ $params->{type_consent} ]` – Tanktalus Jan 24 '17 at 21:27
  • Yeah... unfortunately that's the way the API works :( . I didn't even know I could do that "either one or the other" thing in perl. Thanks A LOT. <3 – Leitouran Jan 24 '17 at 23:50