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

David Schmidt davewood at gmx.at
Fri Jan 8 13:46:32 GMT 2010


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 |
+---------+---------+



More information about the DBIx-Class mailing list