DBIx::Class many_to_many problems

3 messages Options
Embed this post
Permalink
Shawn Marincas

DBIx::Class many_to_many problems

Reply Threaded More More options
Print post
Permalink
Hello, I'm having a trouble accessing resultsets through a many-to-many relationship defined by my schema.  I have a products table and a categories table that are related many-to-many so that products can be in multiple categories.  This is the example they give in the DBIx::Class::Manual::Cookbook for a straightforward configuration using ManyToMany is:

  package My::User;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
__PACKAGE__->many_to_many('addresses' => 'user_address', 'address');

package My::UserAddress;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user_address');
__PACKAGE__->add_columns(qw/user address/);
__PACKAGE__->set_primary_key(qw/user address/);
__PACKAGE__->belongs_to('user' => 'My::User');
__PACKAGE__->belongs_to('address' => 'My::Address');

package My::Address;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('address');
__PACKAGE__->add_columns(qw/id street town area_code country/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
__PACKAGE__->many_to_many('users' => 'user_address', 'user');

$rs = $user->addresses(); # get all addresses for a user
$rs = $address->users(); # get all users for an address


Here is my configuration:

package MyAppDB::Product;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Products');
__PACKAGE__->add_columns(qw/product_id name sku vendor_id price height width depth diameter color weight description info img_thumb img_large date_added shipping availability is_favorite importance/);
__PACKAGE__->set_primary_key(qw/product_id/);

# Vendor relationship
__PACKAGE__->belongs_to(vendor => 'MyAppDB::Vendor', 'vendor_id');

# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'product_id');
__PACKAGE__->many_to_many('categories' => 'product_categories', 'category_id');

1;

package MyAppDB::ProductCategoryLink;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('ProductCategoryLink');
__PACKAGE__->add_columns(qw/product_id category_id/);
__PACKAGE__->set_primary_key(qw/product_id category_id/);

# belongs_to():
__PACKAGE__->belongs_to(product => 'MyAppDB::Product', 'product_id');

# belongs_to():
__PACKAGE__->belongs_to(category => 'MyAppDB::Category', 'category_id');

1;


package MyAppDB::Category;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Categories');
__PACKAGE__->add_columns(qw/category_id name/);
__PACKAGE__->set_primary_key(qw/category_id/);


# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'category_id');
__PACKAGE__->many_to_many('products' => 'product_categories', 'product');

1;


In my Catalyst controller I try and access all the Products of a given Category like so:

       $c->stash->{products} = [$c->model('MyAppDB::Category')->search({ name => $category })->products];

And receive the following error:

"Can't locate object method "products" via package "DBIx::Class::ResultSet"

I am using Catalyst 5.80007 on CentOS 5.0 x64 with MySQL 14.12... I have setup the database tables with the InnoDB engine and setup the foreign keys in the link table.  I don't know what else I could be missing here... anyone have ideas where I could be going wrong?  I'm a relatively new user of both Catalyst and DBIx::Class.  Thanks so much.

- Shawn Marincas

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
fREW Schmidt

Re: DBIx::Class many_to_many problems

Reply Threaded More More options
Print post
Permalink
On Sat, Jul 11, 2009 at 3:15 PM, Shawn Marincas <[hidden email]> wrote:
Hello, I'm having a trouble accessing resultsets through a many-to-many relationship defined by my schema.  I have a products table and a categories table that are related many-to-many so that products can be in multiple categories.  This is the example they give in the DBIx::Class::Manual::Cookbook for a straightforward configuration using ManyToMany is:

  package My::User;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
__PACKAGE__->many_to_many('addresses' => 'user_address', 'address');

package My::UserAddress;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user_address');
__PACKAGE__->add_columns(qw/user address/);
__PACKAGE__->set_primary_key(qw/user address/);
__PACKAGE__->belongs_to('user' => 'My::User');
__PACKAGE__->belongs_to('address' => 'My::Address');

package My::Address;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('address');
__PACKAGE__->add_columns(qw/id street town area_code country/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
__PACKAGE__->many_to_many('users' => 'user_address', 'user');

$rs = $user->addresses(); # get all addresses for a user
$rs = $address->users(); # get all users for an address


Here is my configuration:

package MyAppDB::Product;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Products');
__PACKAGE__->add_columns(qw/product_id name sku vendor_id price height width depth diameter color weight description info img_thumb img_large date_added shipping availability is_favorite importance/);
__PACKAGE__->set_primary_key(qw/product_id/);

# Vendor relationship
__PACKAGE__->belongs_to(vendor => 'MyAppDB::Vendor', 'vendor_id');

# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'product_id');
__PACKAGE__->many_to_many('categories' => 'product_categories', 'category_id');

1;

package MyAppDB::ProductCategoryLink;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('ProductCategoryLink');
__PACKAGE__->add_columns(qw/product_id category_id/);
__PACKAGE__->set_primary_key(qw/product_id category_id/);

# belongs_to():
__PACKAGE__->belongs_to(product => 'MyAppDB::Product', 'product_id');

# belongs_to():
__PACKAGE__->belongs_to(category => 'MyAppDB::Category', 'category_id');

1;


package MyAppDB::Category;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Categories');
__PACKAGE__->add_columns(qw/category_id name/);
__PACKAGE__->set_primary_key(qw/category_id/);


# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'category_id');
__PACKAGE__->many_to_many('products' => 'product_categories', 'product');

1;


In my Catalyst controller I try and access all the Products of a given Category like so:

       $c->stash->{products} = [$c->model('MyAppDB::Category')->search({ name => $category })->products];

And receive the following error:

"Can't locate object method "products" via package "DBIx::Class::ResultSet"

I am using Catalyst 5.80007 on CentOS 5.0 x64 with MySQL 14.12... I have setup the database tables with the InnoDB engine and setup the foreign keys in the link table.  I don't know what else I could be missing here... anyone have ideas where I could be going wrong?  I'm a relatively new user of both Catalyst and DBIx::Class.  Thanks so much.

- Shawn Marincas

It's because you are doing a search, which returns a resultset, and you are using products, which would be chained off of the category class.  You probably want to do something like this:

 $c->stash->{products} = [$c->model('MyAppDB::Category')->single({ name => $category })->products];

That will return the first (and presumably only) category that has the name you passed in.  If you do have more than one category with that name you will get an error.  In that case you could say first instead of single.

HTH
--
fREW Schmidt
http://blog.afoolishmanifesto.com

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Shawn Marincas

Re: DBIx::Class many_to_many problems

Reply Threaded More More options
Print post
Permalink
Thank you kind sir, that worked spectacularly.

On Sat, Jul 11, 2009 at 2:31 PM, fREW Schmidt <[hidden email]> wrote:
On Sat, Jul 11, 2009 at 3:15 PM, Shawn Marincas <[hidden email]> wrote:
Hello, I'm having a trouble accessing resultsets through a many-to-many relationship defined by my schema.  I have a products table and a categories table that are related many-to-many so that products can be in multiple categories.  This is the example they give in the DBIx::Class::Manual::Cookbook for a straightforward configuration using ManyToMany is:

  package My::User;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
__PACKAGE__->many_to_many('addresses' => 'user_address', 'address');

package My::UserAddress;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('user_address');
__PACKAGE__->add_columns(qw/user address/);
__PACKAGE__->set_primary_key(qw/user address/);
__PACKAGE__->belongs_to('user' => 'My::User');
__PACKAGE__->belongs_to('address' => 'My::Address');

package My::Address;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('address');
__PACKAGE__->add_columns(qw/id street town area_code country/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
__PACKAGE__->many_to_many('users' => 'user_address', 'user');

$rs = $user->addresses(); # get all addresses for a user
$rs = $address->users(); # get all users for an address


Here is my configuration:

package MyAppDB::Product;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Products');
__PACKAGE__->add_columns(qw/product_id name sku vendor_id price height width depth diameter color weight description info img_thumb img_large date_added shipping availability is_favorite importance/);
__PACKAGE__->set_primary_key(qw/product_id/);

# Vendor relationship
__PACKAGE__->belongs_to(vendor => 'MyAppDB::Vendor', 'vendor_id');

# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'product_id');
__PACKAGE__->many_to_many('categories' => 'product_categories', 'category_id');

1;

package MyAppDB::ProductCategoryLink;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('ProductCategoryLink');
__PACKAGE__->add_columns(qw/product_id category_id/);
__PACKAGE__->set_primary_key(qw/product_id category_id/);

# belongs_to():
__PACKAGE__->belongs_to(product => 'MyAppDB::Product', 'product_id');

# belongs_to():
__PACKAGE__->belongs_to(category => 'MyAppDB::Category', 'category_id');

1;


package MyAppDB::Category;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('Categories');
__PACKAGE__->add_columns(qw/category_id name/);
__PACKAGE__->set_primary_key(qw/category_id/);


# Category many-to-many relationship
__PACKAGE__->has_many('product_categories' => 'MyAppDB::ProductCategoryLink', 'category_id');
__PACKAGE__->many_to_many('products' => 'product_categories', 'product');

1;


In my Catalyst controller I try and access all the Products of a given Category like so:

       $c->stash->{products} = [$c->model('MyAppDB::Category')->search({ name => $category })->products];

And receive the following error:

"Can't locate object method "products" via package "DBIx::Class::ResultSet"

I am using Catalyst 5.80007 on CentOS 5.0 x64 with MySQL 14.12... I have setup the database tables with the InnoDB engine and setup the foreign keys in the link table.  I don't know what else I could be missing here... anyone have ideas where I could be going wrong?  I'm a relatively new user of both Catalyst and DBIx::Class.  Thanks so much.

- Shawn Marincas

It's because you are doing a search, which returns a resultset, and you are using products, which would be chained off of the category class.  You probably want to do something like this:

 $c->stash->{products} = [$c->model('MyAppDB::Category')->single({ name => $category })->products];

That will return the first (and presumably only) category that has the name you passed in.  If you do have more than one category with that name you will get an error.  In that case you could say first instead of single.

HTH
--
fREW Schmidt
http://blog.afoolishmanifesto.com

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...


_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...