[Catalyst] The Definitive Guide to Catalyst ... p. 165 listing all users and their roles

fREW Schmidt frioux at gmail.com
Wed Jul 11 16:26:48 GMT 2012


Instead of role.role_id.role you should do role.role.role

obviously that's silly in how confusing it is, so eventually if I were you
i'd make the column in the role table to be called name, and then instead
of calling user_roles role, call then user_role.  That would make the above
user_role.role.name.

Sorry, for the top post, replying from my phone
On Jul 11, 2012 10:58 AM, "Robyn Jonahs" <learn.catalyst at gmail.com> wrote:

> Hi,
>
> I am working through the chapter in the book to learn about many to many
> relationship bridges.
>
> I have made it through the chapter up to the last part where it has us
> list all users and their roles. Page 165 in Chapter 6.
>
> This is the template file root/authusers/list.tt
>
> <html>
> <head>
>   <title>All users and their roles</title>
> </head>
> <body>
>
> <table>
>   <tr><th>UserID</th><th>
> Username</th><th>eMail</th><th>Roles</th></tr>
>   [% WHILE (user =3D users_rs.next) %]
>     <tr>
>       <td>[% user.id %]</td>
>       <td>[% user.username %]</td>
>       <td>[% user.email %]</td>
>       <td>
>         <ul>
>           [% FOREACH role =3D user.user_roles %]
>             <li>[% role.role_id.role %]</li>
>           [% END %]
>         </ul>
>       </td>
>     </tr>
>   [% END %]
> </table>
>
> </body>
> </html>
>
>
> If I remove the last "role" in the FOREACH loop it will list the id for
> the roles. It fails to list the text associated with the roles and I can't
> figure out what is going wrong. The only major difference between the book
> and what has happened for me locally is that DBIx::Class::Schema::Loader
> (version 0.07025 ) created the schema results as
>
> DBAuthTest$ ls lib/Auth/Schema/Result/
> Role.pm        User.pm        UserRole.pm
>
> Not the plurals as in the book (Roles.pm, User.pm and UserRoles.pm). I
> have been trying to track these names and keep it consistent with what I =
am
> doing as opposed to the book instructions and so far I have worked through
> it.
>
> The result gives the <li> dots but no values. So it is counting them
> correctly but not retrieving the values. I am stumped on this and any help
> at all would be greatly appreciated.
>
>
>
>
>
>
>
> The other relevant files are:
> =3D=3D=3D=3D=3D=3D=3D=3D The Controller =3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> lib/DBAuthTest/Controller/AuthUsers.pm
>
>
>
> package DBAuthTest::Controller::AuthUsers;
> use Moose;
> use namespace::autoclean;
>
> BEGIN {extends 'Catalyst::Controller'; }
>
> =3Dhead1 NAME
>
> DBAuthTest::Controller::AuthUsers - Catalyst Controller
>
> =3Dhead1 DESCRIPTION
>
> Catalyst Controller.
>
> =3Dhead1 METHODS
>
> =3Dcut
>
>
> =3Dhead2 index
>
> =3Dcut
>
> sub base : Chained('/'): PathPart('authusers'): CaptureArgs(0) {
>     my ( $self, $c ) =3D @_;
>
>     $c->stash(users_rs =3D> $c->model('AuthDB::User'));
>     $c->stash(roles_rs =3D> $c->model('AuthDB::Role'));
> }
>
>
> sub add : Chained('base'): PathPart('add'): Args(0) {
>   my ( $self, $c ) =3D @_;
>
>   if(lc $c->req->method eq 'post') {
>     my $params =3D $c->req->params;
>
>     ## Retrieve the users_rs stashed by the base action:
>     my $users_rs =3D $c->stash->{users_rs};
>
>     ## Create the user:
> =3Dhead2 Original Code
>   - keep for now as I don't trust the code below.
>
>     my $newuser =3D $users_rs->create({
>         username =3D> $params->{username},
>         email    =3D> $params->{email},
>         password =3D> $params->{password},
>     });
> =3Dcut
> =3Dhead2 Catching Errors
>   - No Workiee, not in their code either.
> =3Dcut
>     my $newuser =3D eval { $users_rs->create({
>       username =3D> $params->{username},
>       email    =3D> $params->{email},
>       password =3D> $params->{password},
>     }) };
>     if($@) {
>       $c->log->debug(
>         "User tried to sign up with an invalid email address, redoing..."=
);
>       $c->stash( errors =3D> { email =3D> 'invalid' }, err =3D> $@ );
>       return;
>     }
>
>     return $c->res->redirect( $c->uri_for(
>         $c->controller('AuthUsers')->action_for('profile'),
>         [ $newuser->id ]
>     ) );
>
>   }
>
> }
>
>
> sub user : Chained('base'): PathPart(''): CaptureArgs(1) {
>   my ($self, $c, $userid) =3D @_;
>
>   my $user =3D $c->stash->{users_rs}->find({ id =3D> $userid },{ key =3D>
> 'primary' });
>
>   die "No such user" if(!$user);
>
>   $c->stash(user =3D> $user);
> }
>
>
> sub profile : Chained('user') :PathPart('profile'): Args(0) {
>   my ($self, $c) =3D @_;
>
> }
>
>
> sub edit : Chained('user') :PathPart('edit'): Args(0) {
>   my ($self, $c) =3D @_;
>
>   if(lc $c->req->method eq 'post') {
>     my $params =3D $c->req->params;
>     my $user    =3D $c->stash->{user};
>
>     ## Check user is allowed to update this profile
>     #if($c->user->object->id !=3D $user->id) {
>     #  die "Malicious attempt to update another user by: ".
> $c->user->username;
>     #}
>
>     ## Update user's email and/or password
>     $user->update({
>       email =3D> $params->{email},
>       password =3D> $params->{password},
>     });
>
>     ## Send the user back to the changed profile
>     return $c->res->redirect( $c->uri_for(
>       $c->controller('AuthUsers')->action_for('profile'), [ $user->id ] )
> );
>   }
> }
>
>
> =3Dhead2 Original
> sub set_roles :Chained('user'): PathPart('set_roles'): Args() {
>   my ($self, $c) =3D @_;
>
>   my $user =3D $c->stash->{user};
>   if(lc $c->req->method eq 'post') {
>
>     ## Fetch all role ids submitted as a list
>     my @roles =3D $c->req->param('role');
>
>     ## Remove any existing roles, we're replacing them:
>     $user->user_roles->delete;
>
>     ## Add new roles:
>     foreach my $role_id (@roles) {
>       $user->user_roles->create({ role_id =3D> $role_id });
>     }
>   }
>
>   $c->res->redirect($c->uri_for($c->controller()->action_for('profile'),[
> $user->id ] ));
> }
> =3Dcut
> sub set_roles :Chained('user'): PathPart('set_roles'): Args() {
>   my ($self, $c) =3D @_;
>
>   my $user =3D $c->stash->{user};
>   if(lc $c->req->method eq 'post') {
>
>     ## Fetch all role ids submitted as a list
>     my @roles =3D $c->req->param('role');
>
>     $user->set_all_roles(@roles);
>   }
>
>   $c->res->redirect($c->uri_for($c->controller()->action_for('profile'),
>     [ $user->id ] ));
> }
>
>
> sub delete :Chained('user'): PatPart('delete'): Args() {
>   my ($self, $c) =3D @_;
>   my $user =3D $c->stash->{user};
>   $user->delete();
>
>   return $c->res->redirect( $c->uri_for('/') );
> }
>
>
> sub list : Chained('base'): PathPart('list'): Args(0) {
>   my ($self, $c) =3D @_;
> }
>
> __PACKAGE__->meta->make_immutable;
>
> 1;
>
>
> ------- The Result Classes ------
> DBAuthTest$ ls lib/Auth/Schema/Result/
> Role.pm      User.pm      UserRole.pm
>
>
> =3D=3D=3D=3D=3D=3D=3D=3D User.pm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> use utf8;
> package Auth::Schema::Result::User;
>
> # Created by DBIx::Class::Schema::Loader
> # DO NOT MODIFY THE FIRST PART OF THIS FILE
>
> =3Dhead1 NAME
>
> Auth::Schema::Result::User
>
> =3Dcut
>
> use strict;
> use warnings;
>
> use Moose;
> use MooseX::NonMoose;
> use MooseX::MarkAsMethods autoclean =3D> 1;
> extends 'DBIx::Class::Core';
>
> =3Dhead1 COMPONENTS LOADED
>
> =3Dover 4
>
> =3Ditem * L<DBIx::Class::InflateColumn::DateTime>
>
> =3Ditem * L<DBIx::Class::TimeStamp>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
>
> =3Dhead1 TABLE: C<users>
>
> =3Dcut
>
> __PACKAGE__->table("users");
>
> =3Dhead1 ACCESSORS
>
> =3Dhead2 id
>
>   data_type: 'integer'
>   is_auto_increment: 1
>   is_nullable: 0
>
> =3Dhead2 username
>
>   data_type: 'text'
>   is_nullable: 1
>
> =3Dhead2 email
>
>   data_type: 'text'
>   is_nullable: 1
>
> =3Dhead2 password
>
>   data_type: 'text'
>   is_nullable: 1
>
> =3Dhead2 last_modified
>
>   data_type: 'datetime'
>   is_nullable: 1
>
> =3Dcut
>
> __PACKAGE__->add_columns(
>   "id",
>   { data_type =3D> "integer", is_auto_increment =3D> 1, is_nullable =3D> =
0 },
>   "username",
>   { data_type =3D> "text", is_nullable =3D> 1 },
>   "email",
>   { data_type =3D> "text", is_nullable =3D> 1 },
>   "password",
>   { data_type =3D> "text", is_nullable =3D> 1 },
>   "last_modified",
>   { data_type =3D> "datetime", is_nullable =3D> 1 },
> );
>
> =3Dhead1 PRIMARY KEY
>
> =3Dover 4
>
> =3Ditem * L</id>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->set_primary_key("id");
>
> =3Dhead1 UNIQUE CONSTRAINTS
>
> =3Dhead2 C<username_unique>
>
> =3Dover 4
>
> =3Ditem * L</username>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->add_unique_constraint("username_unique", ["username"]);
>
> =3Dhead1 RELATIONS
>
> =3Dhead2 user_roles
>
> Type: has_many
>
> Related object: L<Auth::Schema::Result::UserRole>
>
> =3Dcut
>
> __PACKAGE__->has_many(
>   "user_roles",
>   "Auth::Schema::Result::UserRole",
>   { "foreign.user_id" =3D> "self.id" },
>   { cascade_copy =3D> 0, cascade_delete =3D> 0 },
> );
>
> =3Dhead2 roles
>
> Type: many_to_many
>
> Composing rels: L</user_roles> -> role
>
> =3Dcut
>
> __PACKAGE__->many_to_many("roles", "user_roles", "role");
>
>
> # Created by DBIx::Class::Schema::Loader v0.07025 @ 2012-07-09 00:18:52
> # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6svl+CkzndehZ8+Zp5yXhw
>
>
> # You can replace this text with custom code or comments, and it will be
> preserved on regeneration
> __PACKAGE__->meta->make_immutable;
>
> __PACKAGE__->add_columns('last_modified',
>   { %{__PACKAGE__->column_info('last_modified') },
>   set_on_create =3D> 1,
>   set_on_update =3D> 1
> });
>
>
> use Email::Valid;
> sub new {
>   my ($class, $args)=3D at _;
>
>   if( exists $args->{email} && !Email::Valid->address($args->{email}) ) {
>     die 'Email invalid';
>   }
>
>   return $class->next::method($args);
> }
>
>
> sub has_role {
>   my ($self, $role) =3D @_;
>
>   ## $role is a row object for a role
>
>   my $roles =3D $self->user_roles->find({ role_id =3D> $role->id });
>   return $roles;
>
> }
>
>
> sub set_all_roles {
>   my ($self, @roleids) =3D @_;
>
>   ## Remove any existing roles, we're replacing them:
>   $self->user_roles->delete;
>
>   ## Add new roles:
>   foreach my $role_id (@roleids) {
>     $self->user_roles->create({ role_id =3D> $role_id });
>   }
>
>   return $self;
> }
>
>
> 1;
>
>
>
> =3D=3D=3D=3D=3D=3D=3D=3D UserRole.pm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
>
>
> use utf8;
> package Auth::Schema::Result::UserRole;
>
> # Created by DBIx::Class::Schema::Loader
> # DO NOT MODIFY THE FIRST PART OF THIS FILE
>
> =3Dhead1 NAME
>
> Auth::Schema::Result::UserRole
>
> =3Dcut
>
> use strict;
> use warnings;
>
> use Moose;
> use MooseX::NonMoose;
> use MooseX::MarkAsMethods autoclean =3D> 1;
> extends 'DBIx::Class::Core';
>
> =3Dhead1 COMPONENTS LOADED
>
> =3Dover 4
>
> =3Ditem * L<DBIx::Class::InflateColumn::DateTime>
>
> =3Ditem * L<DBIx::Class::TimeStamp>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
>
> =3Dhead1 TABLE: C<user_roles>
>
> =3Dcut
>
> __PACKAGE__->table("user_roles");
>
> =3Dhead1 ACCESSORS
>
> =3Dhead2 user_id
>
>   data_type: 'integer'
>   is_foreign_key: 1
>   is_nullable: 0
>
> =3Dhead2 role_id
>
>   data_type: 'integer'
>   is_foreign_key: 1
>   is_nullable: 0
>
> =3Dcut
>
> __PACKAGE__->add_columns(
>   "user_id",
>   { data_type =3D> "integer", is_foreign_key =3D> 1, is_nullable =3D> 0 },
>   "role_id",
>   { data_type =3D> "integer", is_foreign_key =3D> 1, is_nullable =3D> 0 },
> );
>
> =3Dhead1 PRIMARY KEY
>
> =3Dover 4
>
> =3Ditem * L</user_id>
>
> =3Ditem * L</role_id>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->set_primary_key("user_id", "role_id");
>
> =3Dhead1 RELATIONS
>
> =3Dhead2 role
>
> Type: belongs_to
>
> Related object: L<Auth::Schema::Result::Role>
>
> =3Dcut
>
> __PACKAGE__->belongs_to(
>   "role",
>   "Auth::Schema::Result::Role",
>   { id =3D> "role_id" },
>   { is_deferrable =3D> 1, on_delete =3D> "CASCADE", on_update =3D> "CASCA=
DE" },
> );
>
> =3Dhead2 user
>
> Type: belongs_to
>
> Related object: L<Auth::Schema::Result::User>
>
> =3Dcut
>
> __PACKAGE__->belongs_to(
>   "user",
>   "Auth::Schema::Result::User",
>   { id =3D> "user_id" },
>   { is_deferrable =3D> 1, on_delete =3D> "CASCADE", on_update =3D> "CASCA=
DE" },
> );
>
>
> # Created by DBIx::Class::Schema::Loader v0.07025 @ 2012-07-09 00:18:52
> # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:0RYpPqJtXPb7IMPYjImDng
>
>
> # You can replace this text with custom code or comments, and it will be
> preserved on regeneration
> __PACKAGE__->meta->make_immutable;
> 1;
>
>
>
> =3D=3D=3D=3D=3D=3D=3D=3D Role.pm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> use utf8;
> package Auth::Schema::Result::Role;
>
> # Created by DBIx::Class::Schema::Loader
> # DO NOT MODIFY THE FIRST PART OF THIS FILE
>
> =3Dhead1 NAME
>
> Auth::Schema::Result::Role
>
> =3Dcut
>
> use strict;
> use warnings;
>
> use Moose;
> use MooseX::NonMoose;
> use MooseX::MarkAsMethods autoclean =3D> 1;
> extends 'DBIx::Class::Core';
>
> =3Dhead1 COMPONENTS LOADED
>
> =3Dover 4
>
> =3Ditem * L<DBIx::Class::InflateColumn::DateTime>
>
> =3Ditem * L<DBIx::Class::TimeStamp>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
>
> =3Dhead1 TABLE: C<roles>
>
> =3Dcut
>
> __PACKAGE__->table("roles");
>
> =3Dhead1 ACCESSORS
>
> =3Dhead2 id
>
>   data_type: 'integer'
>   is_auto_increment: 1
>   is_nullable: 0
>
> =3Dhead2 role
>
>   data_type: 'text'
>   is_nullable: 1
>
> =3Dcut
>
> __PACKAGE__->add_columns(
>   "id",
>   { data_type =3D> "integer", is_auto_increment =3D> 1, is_nullable =3D> =
0 },
>   "role",
>   { data_type =3D> "text", is_nullable =3D> 1 },
> );
>
> =3Dhead1 PRIMARY KEY
>
> =3Dover 4
>
> =3Ditem * L</id>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->set_primary_key("id");
>
> =3Dhead1 UNIQUE CONSTRAINTS
>
> =3Dhead2 C<role_unique>
>
> =3Dover 4
>
> =3Ditem * L</role>
>
> =3Dback
>
> =3Dcut
>
> __PACKAGE__->add_unique_constraint("role_unique", ["role"]);
>
> =3Dhead1 RELATIONS
>
> =3Dhead2 user_roles
>
> Type: has_many
>
> Related object: L<Auth::Schema::Result::UserRole>
>
> =3Dcut
>
> __PACKAGE__->has_many(
>   "user_roles",
>   "Auth::Schema::Result::UserRole",
>   { "foreign.role_id" =3D> "self.id" },
>   { cascade_copy =3D> 0, cascade_delete =3D> 0 },
> );
>
> =3Dhead2 users
>
> Type: many_to_many
>
> Composing rels: L</user_roles> -> user
>
> =3Dcut
>
> __PACKAGE__->many_to_many("users", "user_roles", "user");
>
>
> # Created by DBIx::Class::Schema::Loader v0.07025 @ 2012-07-09 00:18:52
> # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:a8Hd9uGBQmPWRsNQd8WR6Q
>
>
> # You can replace this text with custom code or comments, and it will be
> preserved on regeneration
> __PACKAGE__->meta->make_immutable;
> 1;
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive:
> http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20120711/df3c5=
c8f/attachment.htm


More information about the Catalyst mailing list