From 902940597067f5e8eaabd1fb125c020acbc0fdb3 Mon Sep 17 00:00:00 2001 From: SpiceMan Date: Wed, 27 Aug 2014 14:05:40 +0900 Subject: [PATCH] add support for row methods to the active_column --- lib/HTML/FormHandler/TraitFor/Model/DBIC.pm | 35 ++++++++++++++++----- t/active_column.t | 24 +++++++++++++- t/lib/BookDB/Schema/Result/Genre.pm | 3 ++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/lib/HTML/FormHandler/TraitFor/Model/DBIC.pm b/lib/HTML/FormHandler/TraitFor/Model/DBIC.pm index 7720978..f5ddac8 100644 --- a/lib/HTML/FormHandler/TraitFor/Model/DBIC.pm +++ b/lib/HTML/FormHandler/TraitFor/Model/DBIC.pm @@ -7,7 +7,7 @@ use Moose::Role; use Carp; use DBIx::Class::ResultClass::HashRefInflator; use DBIx::Class::ResultSet::RecursiveUpdate; -use Scalar::Util ('blessed'); +use Scalar::Util ('blessed', 'looks_like_number'); our $VERSION = '0.26'; @@ -162,6 +162,9 @@ This allows setting the name of the active column globally if your tables are consistantly named (all lookup tables have the same column name to indicate they are active), or on a per-field basis. +The active column can be a row method rather an actual result source column, +but that requires checking each row individually *after* fetching all rows. + The column to use for sorting the list is specified with "sort_column". The currently selected values in a Multiple list are grouped at the top (by the Multiple field class). @@ -373,8 +376,10 @@ sub lookup_options { unless ( $source->has_column($label_column) || $source->result_class->can($label_column) ); - my $active_col = $self->active_column || $field->active_column; - $active_col = '' unless $source->has_column($active_col); + my $active_check = $self->active_column || $field->active_column; + my $active_check_method = $source->result_class->can($active_check) && ! $source->has_column($active_check); + $active_check = '' unless $source->result_class->can($active_check) || $source->has_column($active_check); + my $sort_col = $field->sort_column; my ($primary_key) = $source->primary_columns; @@ -385,10 +390,10 @@ sub lookup_options { $sort_col = $source->has_column($label_column) ? $label_column : $primary_key; } - # If there's an active column, only select active OR items already selected + # If there's an active check, and it's a column, only select active OR items already selected my $criteria = {}; - if ($active_col) { - my @or = ( $active_col => 1 ); + if ($active_check && ! $active_check_method ) { + my @or = ( $active_check => 1 ); # But also include any existing non-active push @or, ( "$primary_key" => $field->init_value ) @@ -401,10 +406,26 @@ sub lookup_options { $self->schema->resultset( $source->source_name ) ->search( $criteria, { order_by => $sort_col } )->all; my @options; + foreach my $row (@rows) { + + # The active check is not a real column, so we must weed rows using the row's method + if( $active_check && $active_check_method ) { + my $is_pk; + + if( $self->item && defined $field->init_value ) { + $is_pk = looks_like_number($row->$primary_key) ? + $row->$primary_key == $field->init_value : + $row->$primary_key eq $field->init_value; + } + + + # skip if not PK nor active + next if ! $row->$active_check && ! $is_pk; + } my $label = $row->$label_column; next unless defined $label; # this means there's an invalid value - push @options, $row->id, $active_col && !$row->$active_col ? "[ $label ]" : "$label"; + push @options, $row->id, $active_check && !$row->$active_check ? "[ $label ]" : "$label"; } return \@options; } diff --git a/t/active_column.t b/t/active_column.t index 7e42b71..c651e3a 100644 --- a/t/active_column.t +++ b/t/active_column.t @@ -22,13 +22,35 @@ use BookDB::Schema; active_column => 'is_active', ); } +{ + package MyApp::Form::Test2; + use HTML::FormHandler::Moose; + extends 'HTML::FormHandler::Model::DBIC'; + + has '+item_class' => ( default => 'Book' ); + has_field 'title' => ( + type => 'Text', + required => 1, + ); + + # has_many relationship pointing to mapping table + has_field 'genres' => ( + type => 'Multiple', + label_column => 'name', + active_column => 'check_active', + ); +} my $schema = BookDB::Schema->connect('dbi:SQLite:t/db/book.db'); my $form = MyApp::Form::Test->new( schema => $schema ); +my $form2 = MyApp::Form::Test2->new( schema => $schema ); ok( $form ); +ok( $form2 ); + +is( $form->field('genres')->num_options, 3, 'right number of options with column' ); +is( $form2->field('genres')->num_options, 3, 'right number of options with method' ); -is( $form->field('genres')->num_options, 3, 'right number of options' ); done_testing; diff --git a/t/lib/BookDB/Schema/Result/Genre.pm b/t/lib/BookDB/Schema/Result/Genre.pm index 7b1fee1..1839a4f 100644 --- a/t/lib/BookDB/Schema/Result/Genre.pm +++ b/t/lib/BookDB/Schema/Result/Genre.pm @@ -25,5 +25,8 @@ BookDB::Schema::Result::Genre->many_to_many( books => 'books_genres', 'book' ); +sub check_active { + $_[0]->is_active; +} 1;