0

Total lack of documentation makes this difficult..

Essentially, I have

package MyApp::Schema;
sub new_schema {
   __PACKAGE__->connect(...)
}

Then I have

package MyCatApp::Model::MyApp;
use Moose;
extends 'Catalyst::Model::DBIC::Schema';

## what here;

_PACKAGE__->make_immutable;

How do I make this work? If I have this in my config...

<Model::MyApp>
        schema_class   MyApp::Schema
        traits Caching
        user_defined_schema_accessor foo
</Model::MyApp>

I get the following error:

BEGIN failed--compilation aborted at MyCatapp.psgi line 4, line 1. Error while loading MyCatapp.psgi: Couldn't instantiate component "Either ->config->{connect_info} must be defined for MyCatApp::Model::MyApp or MyApp::Schema must have connect info defined on it.

But adding sub connect_info {} in MyApp::Schema does not change anything. That error is generated on line 480 of this file.

That method seems to be looking at $schema_class->storage->connect_info which I believe is an method on an instantiated object, and not a function in the package. However, if I try to set

__PACKAGE__->config('schema_class', MyApp::Schema->new_schema)

I then get...

Error while loading : Couldn't instantiate component "MyCatApp::Model::MyApp", "Attribute (schema_class) does not pass the type constraint because: Validation failed for 'Catalyst::Model::DBIC::Schema::Types::SchemaClass' with value MyApp::Schema=HASH(0xb4a5ff0) at /usr/local/lib/perl/5.18.2/Moose/Exception.pm line 37

So, how do I go about doing this...

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468

3 Answers3

0

So.. I'm not sure this is right so I won't mark it as accepted but I was pretty damn close.. This line is dead on..

__PACKAGE__->config('schema_class', MyApp::Schema->new_schema)

And the code is in place for that to work, as per the link above on line 480 of Catalyst::Model::DBIC::Schema. However, the type is wrong..

The type of schema_class is SchemaClass. And, SchemaClass is defined here

subtype SchemaClass,
    as LoadableClass,
    where { $_->isa('DBIx::Class::Schema') };

Now, SchemaClass is a subtype of a MooseX::Types::LoadableClass which essentially just takes a package name and requires it..

The problem is LoadableClass doesn't take an instance of DBIC::Schema. Anyway.. I was just changed it too..

has schema_class => (
    is => 'ro',
    isa => 'Object',
    required => 1
);

Now I can stuff an instantiated schema into schema_class and pass the conditional if($schema_class->storage && $schema_class->storage->connect_info).

I filed a bug on this here

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • The model doesn't want the instantiated dbic schema instance. It wants the class and the connect_info in order to instantiate it itself, which is all i've ever seen done. passing a schema object as a parameter to schema_class doesn't seem proper. your connect_info sub did not return any connection info. It wants to know how to connect to get a connected schema object. – mikew Aug 19 '15 at 04:29
  • the connect_info sub isn't getting called at all. Afaik, the code, as linked, is called `$schema_class->storage->connect_info`. You only have a `$schema_class->storage` if $schema_class, is really already a schema object (if you've already connected). – Evan Carroll Aug 19 '15 at 04:33
0

You could instantiate the connection info in your MyApp::Schema by in it doing:

__PACKAGE__->connection(@your_connection_details);

This will set up a Storage on the class itself, not a schema object. This will then pass the Catalyst::Model::DBIC::Schema check and work successfully. I think this achieves what you're after without changing the underlying classes (though might depend on the details not included).

M Somerville
  • 4,499
  • 30
  • 38
-1

From the documentation you referenced, your MyCatApp::Model::MyApp would look like this:

__PACKAGE__->config(
  schema_class => 'MyApp::Schema',
  connect_info => {
    dsn => 'dbi:Pg:dbname=mypgdb',
    user => 'postgres',
    password => '',
    pg_enable_utf8 => 1,
    on_connect_do => [
      'some SQL statement',
      'another SQL statement',
    ],
  }
);

And in your controller, you would:

my $db = $c->model('MyApp');

mikew
  • 912
  • 2
  • 11
  • 22
  • No, it wouldn't that's one example. My Schema has very complex connection logic, and it can connect itself. I want to let the Schema handle the connection and logic and clearly, as the code referenced supports there is logic to do that... And, as the error message supports the functionality should be there *or MyApp::Schema must have connect info defined on it.* – Evan Carroll Aug 19 '15 at 05:27
  • Ahh good deal then. We also have complicated connection logic but at the end of the day, it's always a dsn, user pass and options. That logic is encapsulated and both the schema and model adapter class use it. In the Model an `around BUILDARGS` modifier is used to call the complicated logic to get the dsn user pass and adjust the connection_info and the model is happily instantiated. Glad you got yours working as well. Cheers. – mikew Aug 19 '15 at 06:07
  • Well, I got mine working by hacking `C:M:DBIC:S`. But, afaik, that was that intent. Unless someone can explain to me how the code on L480 was supposed to work, I think it's a bug. – Evan Carroll Aug 19 '15 at 16:14