[Dbix-class] Re: many_to_many accessor returned object with undef column

David Schmidt davewood at gmx.at
Fri Jan 8 14:12:08 GMT 2010


On Fri, Jan 8, 2010 at 2:46 PM, David Schmidt <davewood at gmx.at> wrote:
> I add some roles, then add a user and give him some roles.
> if i want to print the roles using
>
> foreach ($user->roles) { print "Role: " . $_->name . ", " . $_->id . "\n"; }
>
> I get
>
> Role: admin, 1
> Role: undef, 2
> Role: undef, 3
>
> If I use $_->get_column('name') I get
> Role: admin, 1
> Role: user, 2
> Role: project, 3
>
> Dumping the code with
> die Dumper [$user->roles->search ({}, { result_class =>
> 'DBIx::Class::ResultClass::HashRefInflator'})->all ];
> returns
>
> $VAR1 = [
>          {
>            'name' => 'admin',
>            'id' => '1'
>          },
>          {
>            'name' => 'user',
>            'id' => '2'
>          },
>          {
>            'name' => 'project',
>            'id' => '3'
>          }
>        ];
>
>
> My conclusion:
> the $user->roles accessor returns rows and only the row with id 1
> returns a value for the name column using $row->name. the other rows
> return the value only with $row->get_column('name'). im confused here
> :)
>
> I am a bit out of ideas here, all the details follow. I think its a
> bit fishy that for the admin (with id 1) a name is returned but not
> for the others.
>
>
>
> DBIC_TRACE output:
>
> SELECT me.id, me.name, me.email, me.password, me.created, me.updated,
> me.status FROM users me WHERE ( me.id = ? ): '1'
> SELECT role.id, role.name FROM user_roles me JOIN roles role ON
> role.id = me.role_id WHERE ( me.user_id = ? ): '1'
>
> #SELECT role.id, role.name FROM user_roles me JOIN roles role ON
> role.id = me.role_id WHERE ( me.user_id = 1);
> #+----+---------+
> #| id | name    |
> #+----+---------+
> #|  1 | admin   |
> #+----+---------+
> #|  2 | user    |
> #+----+---------+
> #|  3 | project |
> #+----+---------+
>
> #########
> # USERS #
> #########
>
> __PACKAGE__->table("users");
> __PACKAGE__->add_columns(
>    "id", { ... },
>    "name", { ... },
> );
>
> __PACKAGE__->has_many(
>    'user_roles',
>    'MyApp::Schema::Result::UserRoles',
>    'user_id',
>    { cascade_delete => 1 },
> );
>
> __PACKAGE__->many_to_many(
>    'roles',
>    'user_roles',
>    'role'
> );
>
>
> #########
> # ROLES #
> #########
>
> __PACKAGE__->table("roles");
> __PACKAGE__->add_columns(
>    "id", { ... },
>    "name", { ... },
> );
>
> __PACKAGE__->has_many(
>    'user_roles',
>    'MyApp::Schema::Result::UserRoles',
>    'role_id'
> );
>
> __PACKAGE__->many_to_many(
>    'users',
>    'user_roles',
>    'user'
> );
>
>
> #############
> # USERROLES #
> #############
>
> __PACKAGE__->table("user_roles");
> __PACKAGE__->add_columns(
>    "user_id", { ... },
>    "role_id", { ... },
> );
>
> __PACKAGE__->belongs_to(
>    'user',
>    'MyApp::Schema::Result::Users',
>    'user_id'
> );
>
> __PACKAGE__->belongs_to(
>    'role',
>    'MyApp::Schema::Result::Roles',
>    'role_id'
> );
>
>
> # DATA in DB
> select * from users;
> +----+-------+
> | id | name  |
> +----+-------+
> |  1 | david |
> +----+-------+
>
> select * from roles;
> +----+---------+
> | id | name    |
> +----+---------+
> |  1 | admin   |
> |  3 | project |
> |  2 | user    |
> +----+---------+
>
> select * from user_roles;
> +---------+---------+
> | user_id | role_id |
> +---------+---------+
> |       1 |       1 |
> +---------+---------+
> |       1 |       2 |
> +---------+---------+
> |       1 |       3 |
> +---------+---------+
>


Solved,

the mistake is in

    "name",
    {
        data_type => "varchar",
        is_nullable => 0,
        is_enum => 1,
        extra => { list => [qw/admin/] },
    },

should be

        extra => { list => [qw/admin user project/] },


thanks to everyone who helped in the IRC channel

david



More information about the DBIx-Class mailing list