1

(Similar to, but with more concrete details that, #11526999)

My Result Classes have been built using dbicdump, however I wish to overload the default accessor for a date field.

Works, but a bodge

To hackytest my idea, I simply added an accessor attribute to the created date key of the add_columns call:

__PACKAGE__->add_columns(
  "stamp_id",
  {
    data_type         => "integer",
    is_auto_increment => 1,
    is_nullable       => 0,
    sequence          => "timestamp_stamp_id_seq",
  },
  "date",
  { data_type => "date", is_nullable => 0, accessor => '_date' },
);

... and created my accessor routine below the Schema::Loader checksum line:

# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nB5koMYAhBwz4ET77Q8qlA

sub date {
  my $self = shift;
  warn "overloaded date\n"; # Added for debugging
  my $date;

  # The date needs to be just the date, not the time
  if ( @_ ) {
    $date = shift;
    if ( $date =~ /^([\d\-]+)/ ) {
      $date = $1
    }
    return $self->_date($date)
  }

  # Fetch the column value & remove the time part.
  $date = $self->_date;
  if ( $date =~ /^([\d\-]+)/ ) {
      $date = $1
  }

  return $date;
}

This works, as it returns an expected 2014-10-04, but is a bodge.

Do it the right way

The problem is that I've hacked the checksum'd code, so I can't neatly re-generate my Class objects.

Reading ResultSource and the CookBook the correct approach appears to be:

Have the ResultSource built by dbicdump as standard:

__PACKAGE__->add_columns(
  "stamp_id",
  {
    data_type         => "integer",
    is_auto_increment => 1,
    is_nullable       => 0,
    sequence          => "timestamp_stamp_id_seq",
  },
  "date",
  { data_type => "date", is_nullable => 0 },
);

.... add a change the accessor below the line, using the + to indicate it's an alteration to an existing definition:

# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nB5koMYAhBwz4ET77Q8qlA

__PACKAGE__->add_columns(
  "+date", { accessor => '_date' },
);

.... use the overload method as before

Not working.

I've double-checked my spelling, I've tried add_column rather than add_columns, and I've tried putting the second add_columns to directly below the first - all to now avail.... the code uses the default accessor, and returns 2014-10-04T00:00:00

How do I over-ride the default accessor, so I can use my own method?

Thankee...

smonff
  • 3,399
  • 3
  • 36
  • 46
CodeGorilla
  • 811
  • 1
  • 6
  • 21

2 Answers2

2

What you need here is a col_accessor_map passed in as a loader option.

col_accessor_map => {
  table_name => {
    date => _date,
  }
}

You can pass loader options to dbicdump with -o.

$ dbicdump -o col_accessor_map="{ table_name => { date => _date } }" ... other options ...

(Replace table_name above with the name of your table - that's obvious, right?)

Update: This was posted untested, and when I finally got round to testing it, I found it didn't work. After a conversation with the author on IRC I was told that the col_accessor_map option doesn't support this nested hash approach, so if you wanted to use this approach you would need to use a coderef.

However, the author also agreed that adding this support would be a good idea and I've just got back from lunch to find this Github commit which adds the feature. I don't know how soon it will get to CPAN though.

This may be the first time that CPAN has been updated to make a SO answer correct :-)

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • is there something wrong with the approach I was using? The documentation seems to imply it's the right path... – CodeGorilla Nov 13 '15 at 09:30
  • I can't see anything in the documentation which implies that your `add_columns("+date" ...)` syntax will work. – Dave Cross Nov 13 '15 at 09:33
  • https://metacpan.org/pod/DBIx::Class::Manual::Cookbook#Wrapping-overloading-a-column-accessor describes using the accessor overload and the third paragraph of https://metacpan.org/pod/DBIx::Class::ResultSource#add_columns refers to `('+col1')` - I added the two together, and assumed I could append that syntax to a ResultSource package – CodeGorilla Nov 13 '15 at 10:25
  • You're right. Let me have a look and see if I can work out what the problem is. – Dave Cross Nov 13 '15 at 10:29
  • Upgraded `DBIx::Class::Schema::Loader` to 0.07044 (or later) to get the `col_accessor_map` functionality. Then adding `-o col_accessor_map="{ table_name => { date => '_date' } }"` to the command line (and note the quotes around the `_date` - essential!) – CodeGorilla Feb 18 '16 at 08:47
  • Yeah. Here's the commit that fixed the problem - https://github.com/dbsrgits/dbix-class-schema-loader/commit/3a7a1d7726d84d0970d8ff8e8107fc52e3af0f53 – Dave Cross Feb 18 '16 at 08:50
0

At a different level of abstraction I believe you could use a method modifier

use Class::Method::Modifier; # or Moose/Moo
around date => sub {...};
ashley
  • 559
  • 5
  • 13