Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: Change DBI database on runtime

by zwon (Monsignor)
on Nov 13, 2011 at 04:13 UTC ( #937790=note: print w/ replies, xml ) Need Help??


in reply to Change DBI database on runtime

Usually you have just one instance of given model which is reused for multiple requests. In your case you probably need separate instance for every user (or maybe you can reconfigure single existing instance on a per-request basis, I don't know, it depends), solution that comes to my mind is to use Catalyst::Model::Factory::PerRequest from Catalyst::Model::Adaptor.


Comment on Re: Change DBI database on runtime
Re^2: Change DBI database on runtime
by miguelele (Beadle) on Nov 13, 2011 at 15:55 UTC

    Wow!, isn't it overkill just for a string with the name of the database?, a name that (yes or yes) must be used in each request?

    It seems strange that I can't split up the connection data from the schema itself

    I have been looking for info on the plugins you mention. Thank you!! and Factory::PerRequest seems to be a solution, but info is very schematic. I am still learning from tutorials!!!

    What i have is this model:

    package the_application::Model::DB; use strict; use base 'Catalyst::Model::DBIC::Schema'; __PACKAGE__->config( schema_class => 'the_application::Schema', connect_info => { dsn => 'dbi:mysql:database_one:the_domain.com', user => 'the_user', password => 'the_password', AutoCommit => q{1}, } ); 1;

    - How can I wrap it using Factory::PerRequest and change "dsn" on the fly from a Controller?

    Regards

      Wow!, isn't it overkill just for a string with the name of the database?, a name that (yes or yes) must be used in each request?

      Well, actually no, normally this name is used only once, when you're instantiating model the first time. It's a rather weird idea to use different databases for different users.

      As for how to do this... Look documentation for Catalyst::Model::Adapter, you need to define prepare_arguments and mangle_arguments methods. If you want more control (and you probably do, you can cache models for different users), you can write your own ACCEPT_CONTEXT method (see docs for Catalyst::Component and sources of Catalyst::Model::Factory). All this may be a bit tricky, and documentation is not especially verbose, but I'm sure you will enjoy the process.

        Yes, I am enjoying it because I am learning other things in the process. But info is very raw and other sources are too complex. Not very enjoyable.

        Now I am stuck in the ACCEPT_CONTEXT concept. I can feel "the thing" almost there, but I still haven't seen it :-)

        Thanks

        Obviously, there is something big that I do not understand in the Adaptor/Factory/Factory::PerRequest question.
        - I have the working db class posted before, called 'DB'
        - Now I wrap it from this new model called 'DBWrapper'. And I call this one from the Controller.
        - I need to configure the __PACKAGE__ to avoid compile errors from DBI. Configuration data must be present. I do not understand it, because this info should be replaced from the info coming from the request.
        - The ACCEPT_CONTEXT sub really executes. I see the required info printed in the log (THEALIAS comes from Fastcgi/Nginx custom variable)

        In the end it always query the db named "database_one" configured here, but it ignores the dynamic one from ACCEPT_CONTEXT. I tried also static values, but obviously there is something that I am doing very bad

        Really lost.

        package the_application::Model::DBWrapper; use strict; use warnings; use parent 'Catalyst::Model::Factory::PerRequest'; __PACKAGE__->config( class => 'PWC::Model::DB', connect_info => { dsn => 'dbi:mysql:database_one:the_domain.com', user => 'the_user', password => 'the_password', AutoCommit => q{1}, } ); use Moose; use namespace::autoclean; sub ACCEPT_CONTEXT { my($self, $c) = @_; # Current db name comes from fastcgi enviromental variable from Ng +inx my $current_db = $c->engine->env->{THEALIAS}; $c->log->debug('*** Reached ACCEPT_CONTEXT current db = ' . $curre +nt_db); my $new = $self->meta->clone_object($self, connect_info => { dsn => 'dbi:mysql:' . $current_db . ':the_domain.com', user => 'the_user', password => 'the_password', AutoCommit => q{1}, } ); return $new; } 1;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://937790]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (9)
As of 2014-07-30 06:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (229 votes), past polls