[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