[Jifty-commit] r1869 - in jifty/trunk: lib/Jifty
lib/Jifty/Action/Record t/TestApp-Plugin-REST/t t/TestApp/t
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Sun Aug 27 01:17:14 EDT 2006
Author: nelhage
Date: Sun Aug 27 01:17:11 2006
New Revision: 1869
Added:
jifty/trunk/lib/Jifty/Action/Record/Search.pm
jifty/trunk/t/TestApp/t/12-search.t (contents, props changed)
Modified:
jifty/trunk/lib/Jifty/ClassLoader.pm
jifty/trunk/t/TestApp-Plugin-REST/t/02-basic-use.t
jifty/trunk/t/TestApp/lib/TestApp/Model/User.pm
Log:
Initial version of Jifty::Action::Record::Search. It only supports
exact positive searches on fields at the moment.
Added: jifty/trunk/lib/Jifty/Action/Record/Search.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Action/Record/Search.pm Sun Aug 27 01:17:11 2006
@@ -0,0 +1,116 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Action::Record::Search
+
+=head1 DESCRIPTION
+
+The class is a base class for L<Jifty::Action>s that serve to provide
+an interface to general searches through L<Jifty::Record> objects. To
+use it, subclass it and override the C<record_class> method to return
+the fully qualified name of the model to do searches over.
+
+=cut
+
+package Jifty::Action::Record::Search;
+use base qw/Jifty::Action::Record/;
+
+=head1 METHODS
+
+=head2 arguments
+
+Remove validators from arguments, as well as ``mandatory''
+restrictions. Remove any arguments that render as password fields, or
+refer to collections.
+
+=cut
+
+sub arguments {
+ my $self = shift;
+ return $self->_cached_arguments if $self->_cached_arguments;
+
+ my $args = $self->SUPER::arguments;
+ for my $field (keys %$args) {
+
+ my $info = $args->{$field};
+
+ my $column = $self->record->column($field);
+ # First, modify the ``exact match'' search field (same name as
+ # the original argument)
+
+ delete $info->{validator};
+ delete $info->{mandatory};
+
+ if($info->{valid_values}) {
+ my $valid_values = $info->{valid_values};
+ $valid_values = [$valid_values] unless ref($valid_values) eq 'ARRAY';
+ unshift @$valid_values, "";
+ }
+
+ if(lc $info->{'render_as'} eq 'password') {
+ delete $args->{$field};
+ }
+ if($column && defined(my $refers_to = $column->refers_to)) {
+ delete $args->{$field}
+ if UNIVERSAL::isa($refers_to, 'Jifty::Collection');
+ }
+ # XXX TODO: What about booleans? Checkbox doesn't quite work,
+ # since there are three choices: yes, no, either.
+
+ # XXX TODO: Create arguments for comparisons and substring
+ # matching
+ }
+
+ return $self->_cached_arguments($args);
+}
+
+=head2 take_action
+
+Return a collection with the result of the search specified by the
+given arguments.
+
+We interpret a C<undef> argument as SQL C<NULL>, and ignore empty or
+non-present arguments.
+
+=cut
+
+sub take_action {
+ my $self = shift;
+
+ my $collection = Jifty::Collection->new(
+ record_class => $self->record_class,
+ current_user => $self->record->current_user
+ );
+
+ $collection->unlimit;
+
+ for my $field (grep {$self->has_argument($_)} $self->argument_names) {
+ my $value = $self->argument_value($field);
+ if(defined($value)) {
+ next if $value =~ /^\s*$/;
+ $collection->limit(
+ column => $field,
+ value => $value
+ );
+ } else {
+ $collection->limit(
+ column => $field,
+ value => 'NULL',
+ operator => 'IS'
+ );
+ }
+ }
+
+ $self->result->content(search => $collection);
+ $self->result->success;
+}
+
+=head1 SEE ALSO
+
+L<Jifty::Action::Record>, L<Jifty::Collection>
+
+=cut
+
+1;
Modified: jifty/trunk/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/trunk/lib/Jifty/ClassLoader.pm (original)
+++ jifty/trunk/lib/Jifty/ClassLoader.pm Sun Aug 27 01:17:11 2006
@@ -138,7 +138,7 @@
. "use base qw/@{[$base]}::Collection/;\n"
. "sub record_class { '@{[$base]}::Model::$1' }\n"
. "1;" );
- } elsif ( $module =~ m!^(?:$base)::Action::(Create|Update|Delete)([^\.]+)$! ) {
+ } elsif ( $module =~ m!^(?:$base)::Action::(Create|Update|Delete|Search)([^\.]+)$! ) {
my $modelclass = $base . "::Model::" . $2;
Jifty::Util->require($modelclass);
@@ -201,7 +201,7 @@
my($short) = $full =~ /::Model::(.*)/;
Jifty::Util->require($full . "Collection");
Jifty::Util->require($base . "::Action::" . $_ . $short)
- for qw/Create Update Delete/;
+ for qw/Create Update Delete Search/;
}
}
Modified: jifty/trunk/t/TestApp-Plugin-REST/t/02-basic-use.t
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-REST/t/02-basic-use.t (original)
+++ jifty/trunk/t/TestApp-Plugin-REST/t/02-basic-use.t Sun Aug 27 01:17:11 2006
@@ -14,7 +14,7 @@
use lib 't/lib';
use Jifty::SubTest;
-use Jifty::Test tests => 60;
+use Jifty::Test tests => 61;
use Jifty::Test::WWW::Mechanize;
my $server = Jifty::Test->make_server;
@@ -87,6 +87,7 @@
my @actions = qw(TestApp::Plugin::REST::Action::CreateUser
TestApp::Plugin::REST::Action::UpdateUser
TestApp::Plugin::REST::Action::DeleteUser
+ TestApp::Plugin::REST::Action::SearchUser
TestApp::Plugin::REST::Action::DoSomething
Jifty::Action::Autocomplete
Jifty::Action::Redirect);
Modified: jifty/trunk/t/TestApp/lib/TestApp/Model/User.pm
==============================================================================
--- jifty/trunk/t/TestApp/lib/TestApp/Model/User.pm (original)
+++ jifty/trunk/t/TestApp/lib/TestApp/Model/User.pm Sun Aug 27 01:17:11 2006
@@ -1,5 +1,6 @@
package TestApp::Model::User::Schema;
use Jifty::DBI::Schema;
+use Scalar::Defer;
# Your column definitions go here. See L<Jifty::DBI::Schema> for
# documentation about how to write column definitions.
@@ -13,6 +14,16 @@
column 'tasty' =>
type is 'boolean',
is immutable;
+column 'password' =>
+ type is 'text',
+ render_as 'Password',
+ is mandatory,
+ default is '';
+column 'created_on' =>
+ type is 'datetime',
+ is immutable,
+ default is defer { DateTime->now },
+ filters are 'Jifty::DBI::Filter::DateTime';
package TestApp::Model::User;
Added: jifty/trunk/t/TestApp/t/12-search.t
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp/t/12-search.t Sun Aug 27 01:17:11 2006
@@ -0,0 +1,136 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+=head1 DESCRIPTION
+
+Test Jifty::Action::Record::Search
+
+=cut
+
+use lib 't/lib';
+use lib 't/lib';
+use Jifty::SubTest;
+
+use Jifty::Test qw(no_plan);
+
+my $user = TestApp::Model::User->new(current_user => TestApp::CurrentUser->superuser);
+
+ok($user->create(
+ name => 'test1',
+ email => 'test1 at localhost',
+ password => 'secret',
+ tasty => 0,
+ created_on => '2006-07-08 19:30'
+ ),
+ "Created one user"
+);
+
+$user = TestApp::Model::User->new(current_user => TestApp::CurrentUser->superuser);
+
+ok($user->create(
+ name => 'test2',
+ email => 'test2 at example.com',
+ password => 'password',
+ tasty => 1,
+ created_on => '2005-09-02 15:16'
+ ),
+ "Created another user"
+);
+
+
+$user = TestApp::Model::User->new(current_user => TestApp::CurrentUser->superuser);
+
+ok($user->create(
+ name => 'third_test',
+ email => 'test3 at not.a.domain',
+ password => 'hahaha',
+ created_on => '1999-12-31 23:59'
+ ),
+ "Created a third user"
+);
+
+
+# Set up Jifty so we can call J->w->new_action
+Jifty->new;
+Jifty->web->request(Jifty::Request->new);
+Jifty->web->response(Jifty::Response->new);
+
+my $search = Jifty->web->new_action(
+ class => 'SearchUser',
+ moniker => 'search',
+ current_user => TestApp::CurrentUser->superuser,
+ arguments => {}
+);
+
+isa_ok($search, 'Jifty::Action::Record::Search');
+
+my %args = %{$search->arguments};
+
+ok($args{name}, "Can search on name");
+ok(!$args{name}{mandatory}, "Fields aren't mandatory");
+ok($args{email}, "Can search on email");
+ok($args{tasty}, "Can search on tastiness");
+ok($args{created_on}, "Can search on created_on");
+ok(!$args{password}, "Can't search on password");
+
+
+# Search on name
+$search->argument_values({name => 'test1'});
+$search->run;
+
+my $result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 1);
+is($result->first->name, 'test1');
+
+# Search on email
+$search->argument_values({email => 'test2 at example.com'});
+$search->run;
+
+$result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 1);
+is($result->first->name, 'test2');
+
+# Search on tastiness
+$search->argument_values({tasty => 1});
+$search->run;
+
+$result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 1);
+is($result->first->name, 'test2');
+
+# Search for a NULL tastiness
+$search->argument_values({tasty => undef});
+$search->run;
+
+$result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 1);
+is($result->first->name, 'third_test');
+
+# An empty search should return everything
+$search->argument_values({});
+$search->run;
+
+$result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 3);
+
+# We ignore empty but defined fields
+
+$search->argument_values({email => "", name => 'third_test'});
+$search->run;
+
+$result = $search->result->content('search');
+
+isa_ok($result, 'Jifty::Collection');
+is($result->count, 1);
+is($result->first->name, 'third_test');
More information about the Jifty-commit
mailing list