0

I've created a model lib/MyApp/Model/Foo.pm. Inside it:

...
sub bar {
  my $schema = MyApp::Schem->connect("dbi:SQLite:data.db");
}
...

It works fine but when I write so:

...
my $schema = MyApp::Schema->connect("dbi:SQLite:data.db");
sub bar {}
...

it doesn't work and write this:

Can't locate object method "connect" via package "MyApp::Schema" (perhaps you forgot to load "MyApp::Schema"?) at ...

I'd like to create global $schema var to use it in different methods. How can I reach it?

edem
  • 3,222
  • 3
  • 19
  • 45
  • Since you're using catalyst you could initialize the schema when the application starts using a singleton. Then it should be available throughout the application. – jmcneirney Mar 21 '13 at 15:20

3 Answers3

2

Catalyst::Model::DBIC::Schema handles connecting to the database automatically for every process that might be started.

If you create your MyApp::Model::DBIC using the helper as shown in the synopsis it will work out-of-the-box. Database credentials or the database filename in case of SQLite are usually put inside the Catalyst config file loaded by Catalyst::Plugin::ConfigLoader.

Note that you normally don't add any methods to the Catalyst model nor the DBIx::Class schema.

To access the model, regardless of its type (DBIC, LDAP, ...), you have to use $c->model($modelname) in Catalyst. So if you named your model MyApp::Model::DBIC this would be $c->model('DBIC'). To access a DBIC resultset you can either use $c->model('DBIC')->resultset('Foo') or $c->model('DBIC::Foo') which is a special syntax Catalyst::Model::DBIC::Schema supports.

Alexander Hartmaier
  • 2,178
  • 12
  • 21
  • `Note that you normally don't add any methods to the Catalyst model` oh, and where must I keep them? – edem Mar 21 '13 at 17:20
  • 1
    Depends on what the methods should do. If they should be callable onto a DBIC $row object they go into the result class, if its a method for a resultset like for example a predefined search it goes into the resultset class of that table. Those are all DBIx::Class related things and have nothing to do if you use the DBIC model with Catalyst or something else. – Alexander Hartmaier Mar 22 '13 at 10:38
  • Hah, thanks. I didn't know that methods for work with defined table may be kept in resultset class. – edem Mar 22 '13 at 11:12
0

Did you forget to load MyApp::Schema?

When you call MyApp::Schema->connect inside a subroutine, it is likely that some other Catalyst component has already loaded the MyApp::Schema module and made the connect method available.

Outside the subroutine, your application will try to call MyApp::Schema::connect at the time your MyApp::Model::Foo module is loaded, and whether it will succeed or not will depend on the order that other packages are loaded. So writing use MyApp::Schema; at the top of your MyApp::Model::Foo package might solve your problem.


Another thing that might solve your problem is lazy initialization of your schema. Replace all instances of $schema in your model with a function call, say, schema(), and include this code:

my $_schema;
sub schema {
    $_schema //= MyApp::Schem->connect("dbi:SQLite:data.db")
}

Now your schema object gets initialized once, when it's needed, and probably after all the other relevant modules your application depends on have been loaded.

mob
  • 117,087
  • 18
  • 149
  • 283
  • 1
    Your answer doesn't make any sense because if the helper to generate the DBIC model is used the containing code will work out-of-the-box without any guessing. It takes care of loading the schema itself, there is no need to do that manually. – Alexander Hartmaier Mar 21 '13 at 17:01
0

I read in Catalyst::Model::DBIC::Schema that we can us $self->schema to get access to db schema from anywhere. So this variant works fine:

sub bar {
  my ($self) = @_;
  my $schema = $self->schema;
}
edem
  • 3,222
  • 3
  • 19
  • 45