[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