[Catalyst] Sharing a database handle between components

Matt S Trout dbix-class at trout.me.uk
Sat Feb 9 18:06:52 GMT 2008


On Sat, Feb 09, 2008 at 06:39:27PM +0100, Aristotle Pagaltzis wrote:
> Hi all,
> 
> I have the following situation: in our app, some templates need
> to be user-customisable (we do some white-labelling basically),
> so those come from the database. For that, I wire up my view,
> which is TT, with Template::Provider::DBI. But I want T::P::DBI
> to share the same handle used by my model (an app-specific
> abstraction over the database).
> 
> My first problem was that I had no way to get at the app instance
> from within MyApp::View::TT::new, much less from within the
> `__PACKAGE__->config` call at load time. The only way I could
> think of at first was to have `ACCEPT_CONTEXT` check whether
> TT’s `LOAD_TEMPLATES` contained a T::P::DBI instance, and if
> not, stick one in there. But that’s just a hack; the T::P::DBI
> instance needs to be created only once, but this code checks for
> its presence on every request, not to mention it would *create*
> a new instance for every request when running under a forking
> engine and might even break completely under a threading one.
> 
> After a pointer I got from jshirley on IRC I noticed that the
> boilerplate generated by the default helper includes a
> `__PACKAGE__->setup` call at the bottom of MyApp.pm. I felt a
> bit sheepish.
> 
> For some reason, the next thing I tried,
> 
>     sub setup {
>         my $class = shift;
>         $class->NEXT::setup( @_ );
>     }
> 
> didn’t work.
> 
> But never mind that – since I’m calling `__PACKAGE__->setup`,
> I know what’s going to happen so I can just add some code below
> that line.
> 
> So now I have a `add_dbi_provider` method in MyApp::View::TT, and
> then in MyApp.pm I do
> 
>     __PACKAGE__->setup;
>     __PACKAGE__->view('TT')->add_dbi_provider( __PACKAGE__->model('MyApp')->dbh );
> 
> This seems hackish too, but at least it’s far better, I think,
> than the hack I had before.

What was wrong with just making the dbh acquired from -

Scalar::Defer::lazy { $app->model('Foo')->schema->storage->dbh }

? (I'm assuming you're using a DBIC::Schema model, adjust as appropriate
for anything else)
 
> Questions: is this remotely sane? Is there a better way to go
> about all this? Is there a way that will work now *and* after
> the app/context switch jshirley mentioned?

The first argument to COMPONENT is $app

The only difference is at some point it'll be an object rather than a classname.

-- 
      Matt S Trout       Need help with your Catalyst or DBIx::Class project?
   Technical Director                    http://www.shadowcat.co.uk/catalyst/
 Shadowcat Systems Ltd.  Want a managed development or deployment platform?
http://chainsawblues.vox.com/            http://www.shadowcat.co.uk/servers/



More information about the Catalyst mailing list