use Data::Alias;
use Moose;
-use MooseX::Method::Signatures;
+use Method::Signatures::Simple;
extends 'DBIx::Class::ResultSet';
has '_row_info' => (
- is => 'rw',
- isa => 'HashRef'
+ is => 'rw',
+ isa => 'HashRef'
);
has 'was_row' => (
- is => 'rw',
- isa => 'Int'
+ is => 'rw',
+ isa => 'Int'
);
has 'id_cols' => (
- is => 'rw',
- isa => 'ArrayRef',
+ is => 'rw',
+ isa => 'ArrayRef',
);
-
+
+has '_modifiers' => (
+ is => 'rw',
+ isa => 'ArrayRef',
+);
+
+=head1 VERSION
+
+Version 0.999003
+
+=cut
+
+our $VERSION = '0.999003';
+
+=head1 NAME
+
+DBIx::Class::ResultSet::WithMetaData
+
+=head1 SYNOPSIS
+
+ package MyApp::Schema::ResultSet::ObjectType;
+
+ use Moose;
+ use MooseX::Method::Signatures;
+ extends 'DBIx::Class::ResultSet::WithMetaData;
+
+ method with_substr () {
+ $self->build_metadata( modifier => sub () {
+ my $row = shift;
+ my $substr = substr($row->{name}, 0, 3);
+ $row->{substr} = $substr;
+ return $row;
+ });
+ return $self;
+ }
+
+ ...
+
+
+ # then somewhere else
+
+ my $object_type_arrayref = $object_type_rs->with_substr->display();
+
+ # [{
+ # 'artistid' => '1',
+ # 'name' => 'Caterwauler McCrae',
+ # 'substr' => 'Cat'
+ # },
+ # {
+ # 'artistid' => '2',
+ # 'name' => 'Random Boy Band',
+ # 'substr' => 'Ran'
+ # },
+ # {
+ # 'artistid' => '3',
+ # 'name' => 'We Are Goth',
+ # 'substr' => 'We '
+ # }]
+
+=head1 DESCRIPTION
+
+Attach metadata to rows by chaining ResultSet methods together. When the ResultSet is
+flattened to an ArrayRef the attached metadata is merged with the row hashes to give
+a combined 'hash-plus-other-stuff' representation.
+
+=head1 METHODS
+
+=cut
sub new {
- my $self = shift;
+ my $self = shift;
+
+ my $new = $self->next::method(@_);
+ foreach my $key (qw/_row_info was_row id_cols _modifiers/) {
+ alias $new->{$key} = $new->{attrs}{$key};
+ }
- my $new = $self->next::method(@_);
- foreach my $key (qw/_row_info was_row id_cols/) {
- alias $new->{$key} = $new->{attrs}{$key};
- }
+ unless ($new->_row_info) {
+ $new->_row_info({});
+ }
- unless ($new->_row_info) {
- $new->_row_info({});
- }
+ unless ($new->_modifiers) {
+ $new->_modifiers([]);
+ }
- unless ($new->id_cols && scalar(@{$new->id_cols})) {
- $new->id_cols([sort $new->result_source->primary_columns]);
- }
+ unless ($new->id_cols && scalar(@{$new->id_cols})) {
+ $new->id_cols([sort $new->result_source->primary_columns]);
+ }
- return $new;
+ return $new;
}
+=head2 display
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: ArrayRef
+
+=back
+
+ $arrayref_of_row_hashrefs = $rs->display();
+
+This method uses L<DBIx::Class::ResultClass::HashRefInflator> to convert all
+rows in the ResultSet to HashRefs. These are then merged with any metadata
+that had been attached to the rows using L</add_row_info>.
+
+=cut
+
method display () {
my $rs = $self->search({});
$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
my @rows;
- foreach my $row ($rs->all) {
- if (my $info = $self->row_info_for(id => $self->_mk_id(row => $row))) {
- $row = { %{$row}, %{$info} };
- }
- push(@rows, $row);
- }
+ foreach my $row ($rs->all) {
+ # THIS BLOCK IS DEPRECATED
+ if (my $info = $self->row_info_for(id => $self->_mk_id(row => $row))) {
+ $row = { %{$row}, %{$info} };
+ }
+
+ foreach my $modifier (@{$rs->_modifiers}) {
+ my $new_row = $modifier->($row);
+ if (ref $new_row ne 'HASH') {
+ die 'modifier subref (added via build_metadata did not return hashref)';
+ }
+ $row = $new_row;
+ }
+ push(@rows, $row);
+ }
return ($self->was_row) ? $rows[0] : \@rows;
}
-method add_row_info (Int :$id, :$row, HashRef :$info) {
- if ($row) {
- $id = $self->_mk_id(row => { $row->get_columns });
- }
- unless ($self->find($id)) {
- warn $id;
- die 'invalid id passed to add_row_info';
- }
+=head2 build_metadata
- if (my $existing = $self->_row_info->{$id}) {
- $info = { %{$existing}, %{$info} };
- }
+=over 4
- $self->_row_info->{$id} = $info;
-}
+=item Arguments: modifier => subref($row_hash)
+
+=item Return Value: ResultSet
+
+=back
+
+ $self->build_metadata( modifier => sub ($row) {
+ $row->{dates} = [qw/mon weds fri/];
+ return $row;
+ });
+
+This method allows you to alter the hash to add additional metadata to it
+at L</display> time.
+
+=cut
-method row_info_for (Int :$id) {
- return $self->_row_info->{$id};
+method build_metadata (%opts) {
+ my ($modifier) = map { $opts{$_} } qw/modifier/;
+ unless ($modifier && (ref $modifier eq 'CODE')) {
+ die 'build_metadata called without modifier param';
+ }
+
+ push( @{$self->_modifiers}, $modifier );
}
-method order_by (Str :$col) {
- $col = "me.$col" unless ($col =~ m/\./);
- return $self->search({}, { order_by => $col });
+
+=head2 add_row_info (DEPRECATED)
+
+=over 4
+
+=item Arguments: row => DBIx::Class::Row object, info => HashRef to attach to the row
+
+=item Return Value: ResultSet
+
+=back
+
+ $rs = $rs->add_row_info(row => $row, info => { dates => [qw/mon weds fri/] } );
+
+DEPRECATED - this method is quite slow as it requires that you iterate through
+the resultset each time you want to add metadata. Replaced by L</build_metadata>.
+
+=cut
+
+method add_row_info (%opts) {
+ my ($row, $id, $info) = map { $opts{$_} } qw/row id info/;
+
+ warn 'DEPRECATED - add_row_info is deprecated in favour of build_metadata';
+ if ($row) {
+ $id = $self->_mk_id(row => { $row->get_columns });
+ }
+
+ unless ($row || $self->find($id)) {
+ die 'invalid id passed to add_row_info';
+ }
+
+ if (my $existing = $self->_row_info->{$id}) {
+ $info = { %{$existing}, %{$info} };
+ }
+
+ $self->_row_info->{$id} = $info;
}
-method limit (Int :$count) {
- return $self->search({}, { rows => $count });
+# DEPRECATED
+method row_info_for (%opts) {
+ my $id = $opts{id};
+ return $self->_row_info->{$id};
}
-method _mk_id (HashRef :$row) {
- return join('-', map { $row->{$_} } @{$self->id_cols});
+# DEPRECATED
+method _mk_id (%opts) {
+ my $row = $opts{row};
+ return join('-', map { $row->{$_} } @{$self->id_cols});
}
+=head1 AUTHOR
+
+ Luke Saunders <luke.saunders@gmail.com>
+
+=head1 THANKS
+
+As usual, thanks to Matt S Trout for the sanity check.
+
+=head1 LICENSE
+
+ This library is free software under the same license as perl itself
+
+=cut
+
1;