FAQ
Hi,

I am fairly new to all things Perl and Catalyst, and would like to know
if what I am attempting to do is correct.

I've recently finished reading 'The Definitive Guide to Catalyst', which
has been very helpful, but I am still a little confused about separating
my business logic from my Catalyst application, and accessing the
database connection from my non-Catalyst application.

At the moment, I have my external class in the lib/MyApp directory. It
uses the connection info found in MyApp::Model::DB, like so:

---

# lib/MyApp/MyExternalClass.pm
MyApp::MyExternalClass

use MyApp::Model::DB;
use MyApp::Schema;

my $connect_info = MyApp::Model::DB->config->{connect_info};
my $schema = MyApp::Schema->connect( $connect_info );

# Do stuff with $schema...

---

That works, and I can connect to the database. However, I have searched
this mailing list, and found this:

http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg00817.html

Here, the connection information is moved from MyApp::Model::DB to
MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
appears to be part of the Catalyst application, so if I want to access
the database from an external model, it makes sense to me to move the
connection code outside of the Catalyst application.


Regards,

Mike

Search Discussions

  • Octavian Rasnita at Nov 5, 2010 at 10:10 am
    From: "Mike Raynham" <catalyst@mikeraynham.co.uk>
    Hi,

    I am fairly new to all things Perl and Catalyst, and would like to know if
    what I am attempting to do is correct.

    I've recently finished reading 'The Definitive Guide to Catalyst', which
    has been very helpful, but I am still a little confused about separating
    my business logic from my Catalyst application, and accessing the database
    connection from my non-Catalyst application.

    At the moment, I have my external class in the lib/MyApp directory. It
    uses the connection info found in MyApp::Model::DB, like so:

    ---

    # lib/MyApp/MyExternalClass.pm
    MyApp::MyExternalClass

    use MyApp::Model::DB;
    use MyApp::Schema;

    my $connect_info = MyApp::Model::DB->config->{connect_info};
    my $schema = MyApp::Schema->connect( $connect_info );

    # Do stuff with $schema...

    ---

    That works, and I can connect to the database. However, I have searched
    this mailing list, and found this:

    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg00817.html

    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access the
    database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.


    Regards,

    Mike

    The best idea would be to put the connection information in the
    application's config file like in the example below. (This example uses a
    Perl data structure, but you can use any configuration type accepted by
    Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is defined
    in the config file, and you can use the data from this config file in any
    other external program.
    You can use the module Config::JFDI for using the Catalyst config file
    easier.

    Octavian
  • Mike Raynham at Nov 5, 2010 at 11:01 am

    On 05/11/10 10:10, Octavian Rasnita wrote:
    From: "Mike Raynham" <catalyst@mikeraynham.co.uk>
    Hi,

    I am fairly new to all things Perl and Catalyst, and would like to
    know if what I am attempting to do is correct.

    I've recently finished reading 'The Definitive Guide to Catalyst',
    which has been very helpful, but I am still a little confused about
    separating my business logic from my Catalyst application, and
    accessing the database connection from my non-Catalyst application.

    At the moment, I have my external class in the lib/MyApp directory. It
    uses the connection info found in MyApp::Model::DB, like so:

    ---

    # lib/MyApp/MyExternalClass.pm
    MyApp::MyExternalClass

    use MyApp::Model::DB;
    use MyApp::Schema;

    my $connect_info = MyApp::Model::DB->config->{connect_info};
    my $schema = MyApp::Schema->connect( $connect_info );

    # Do stuff with $schema...

    ---

    That works, and I can connect to the database. However, I have
    searched this mailing list, and found this:

    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg00817.html

    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access
    the database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.


    Regards,

    Mike

    The best idea would be to put the connection information in the
    application's config file like in the example below. (This example uses
    a Perl data structure, but you can use any configuration type accepted
    by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is
    defined in the config file, and you can use the data from this config
    file in any other external program.
    You can use the module Config::JFDI for using the Catalyst config file
    easier.

    Octavian
    Hi,

    Thanks for the speedy response. When you put it like like, it all seems
    so simple and obvious :-)

    Config::JFDI looks handy - I'll take a look at that.


    Regards,

    Mike
  • Hernan Lopes at Nov 5, 2010 at 11:43 am
    Mike,

    also, if you havent already, take a look on Catalyst::Tutorial , in my
    opinion its by far the best documentation to begin with catalyst.

    http://search.cpan.org/~zarquon/Catalyst-Manual-5.8005/lib/Catalyst/Manual/Tutorial/01_Intro.pod


    On 11/5/10, Mike Raynham wrote:
    On 05/11/10 10:10, Octavian Rasnita wrote:
    From: "Mike Raynham" <catalyst@mikeraynham.co.uk>
    Hi,

    I am fairly new to all things Perl and Catalyst, and would like to
    know if what I am attempting to do is correct.

    I've recently finished reading 'The Definitive Guide to Catalyst',
    which has been very helpful, but I am still a little confused about
    separating my business logic from my Catalyst application, and
    accessing the database connection from my non-Catalyst application.

    At the moment, I have my external class in the lib/MyApp directory. It
    uses the connection info found in MyApp::Model::DB, like so:

    ---

    # lib/MyApp/MyExternalClass.pm
    MyApp::MyExternalClass

    use MyApp::Model::DB;
    use MyApp::Schema;

    my $connect_info = MyApp::Model::DB->config->{connect_info};
    my $schema = MyApp::Schema->connect( $connect_info );

    # Do stuff with $schema...

    ---

    That works, and I can connect to the database. However, I have
    searched this mailing list, and found this:

    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg00817.html

    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access
    the database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.


    Regards,

    Mike

    The best idea would be to put the connection information in the
    application's config file like in the example below. (This example uses
    a Perl data structure, but you can use any configuration type accepted
    by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is
    defined in the config file, and you can use the data from this config
    file in any other external program.
    You can use the module Config::JFDI for using the Catalyst config file
    easier.

    Octavian
    Hi,

    Thanks for the speedy response. When you put it like like, it all seems
    so simple and obvious :-)

    Config::JFDI looks handy - I'll take a look at that.


    Regards,

    Mike

    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
  • Mike Raynham at Nov 5, 2010 at 12:04 pm

    On 05/11/10 11:43, Hernan Lopes wrote:
    Mike,

    also, if you havent already, take a look on Catalyst::Tutorial , in my
    opinion its by far the best documentation to begin with catalyst.

    http://search.cpan.org/~zarquon/Catalyst-Manual-5.8005/lib/Catalyst/Manual/Tutorial/01_Intro.pod



    On 11/5/10, Mike Raynhamwrote:
    On 05/11/10 10:10, Octavian Rasnita wrote:
    From: "Mike Raynham"<catalyst@mikeraynham.co.uk>
    Hi,

    I am fairly new to all things Perl and Catalyst, and would like to
    know if what I am attempting to do is correct.

    I've recently finished reading 'The Definitive Guide to Catalyst',
    which has been very helpful, but I am still a little confused about
    separating my business logic from my Catalyst application, and
    accessing the database connection from my non-Catalyst application.

    At the moment, I have my external class in the lib/MyApp directory. It
    uses the connection info found in MyApp::Model::DB, like so:

    ---

    # lib/MyApp/MyExternalClass.pm
    MyApp::MyExternalClass

    use MyApp::Model::DB;
    use MyApp::Schema;

    my $connect_info = MyApp::Model::DB->config->{connect_info};
    my $schema = MyApp::Schema->connect( $connect_info );

    # Do stuff with $schema...

    ---

    That works, and I can connect to the database. However, I have
    searched this mailing list, and found this:

    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/msg00817.html

    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access
    the database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.


    Regards,

    Mike

    The best idea would be to put the connection information in the
    application's config file like in the example below. (This example uses
    a Perl data structure, but you can use any configuration type accepted
    by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is
    defined in the config file, and you can use the data from this config
    file in any other external program.
    You can use the module Config::JFDI for using the Catalyst config file
    easier.

    Octavian
    Hi,

    Thanks for the speedy response. When you put it like like, it all seems
    so simple and obvious :-)

    Config::JFDI looks handy - I'll take a look at that.


    Regards,

    Mike

    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/

    Hi,

    Thanks. That's where I started my venture into Perl and Catalyst, and
    it too was very helpful. With this question of separating my model from
    the Catalyst app, I had just overlooked the obvious.


    Regards,

    Mike
  • Darren Duncan at Nov 5, 2010 at 4:50 pm

    Mike Raynham wrote:
    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access
    the database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.
    What you want to do is turn all the stuff that mediates access to the database
    into your own shared library formatted kind of like one you might find as a CPAN
    module, say "MyDBLib", and then "use" it in your Catalyst application by way of
    Catalyst::Model::Adaptor.

    For any configuration details that might vary either per application or per
    deployment, make these user-configurable parameters of MyDBLib, with then each
    of your applications would supply arguments to it when instantiating a MyDBLib
    object; in the Catalyst app's case, said arguments would be in your Catalyst app
    config file as is normal for MyApp::Model::DB.

    For any configuration details that are unlikely to vary per application or per
    deployment, especially if they are details for which your actual code would
    vary, then put these directly in your MyDBLib code instead.

    Octavian Rasnita wrote:
    The best idea would be to put the connection information in the application's config file like in the example below. (This example uses a Perl data structure, but you can use any configuration type accepted by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is defined in the config file, and you can use the data from this config file in any other external program.
    You can use the module Config::JFDI for using the Catalyst config file easier.
    Now some of this looks wrong to me; a lot of those details should be in your
    MyDBLib code instead of the config file. Your config file should instead look
    more like this:

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    host => '10.10.10.10',
    port => 1521,
    user => 'user',
    password => "password",
    },
    },

    These are more details that a non-programmer user would set.

    The other details should all be in your code instead, because users shouldn't
    have to know and in particular if they are changed your code could break. In
    particular I'm thinking of stuff like "on_connect_call" or the fact you are
    using "dbi:Oracle".

    Where it can get fuzzier is if your application is cross-DBMS portable, in which
    case more info would need to be in the config file, but you'd want to abstract
    it somehow, such as users just naming the DBMS and then they are actually
    picking from a pre-defined profile which has the code-specific details. But if
    the app isn't supposed to be portable, eg if it uses Oracle-specific stuff, then
    don't put dbi:Oracle and NLS* and that stuff in your user config file.

    Stuff like LongReadLen might be okay here if and only if changing it just tunes
    performance, like you were setting a chunk-buffer size or something, and would
    have no impact on behavior nor break any code; otherwise don't have it here.

    -- Darren Duncan
  • Octavian Rasnita at Nov 5, 2010 at 7:53 pm
    From: "Darren Duncan" <darren@darrenduncan.net>
    For any configuration details that might vary either per application or per
    deployment, make these user-configurable parameters of MyDBLib, with then each
    of your applications would supply arguments to it when instantiating a MyDBLib
    object; in the Catalyst app's case, said arguments would be in your Catalyst app
    config file as is normal for MyApp::Model::DB.

    For any configuration details that are unlikely to vary per application or per
    deployment, especially if they are details for which your actual code would
    vary, then put these directly in your MyDBLib code instead.

    Yes you are right.
    Octavian Rasnita wrote:
    The best idea would be to put the connection information in the application's config file like in the example below. (This example uses a Perl data structure, but you can use any configuration type accepted by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },
    [snip]
    Now some of this looks wrong to me; a lot of those details should be in your
    MyDBLib code instead of the config file. Your config file should instead look
    more like this:

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    host => '10.10.10.10',
    port => 1521,
    user => 'user',
    password => "password",
    },
    },

    These are more details that a non-programmer user would set.

    I agree and yes, that sample code could give bad ideas.
    In my case I am the app designer, coder, maintainer, site admin, everything but the web designer and I've done it so for not specifying these settings in more places.

    Is there another place where I could put these settings for a certain DBIC schema?
    For example, can I put them in the MyApp/Schema.pm, orsomewhere else? Can you give an example?

    Thanks.

    Octavian
  • Darren Duncan at Nov 6, 2010 at 6:57 pm
    P.S. While answering a question, this email could be adapted for a Catalyst
    cookbook / etc entry if one wants to.

    Octavian Rasnita wrote:
    I agree and yes, that sample code could give bad ideas.
    In my case I am the app designer, coder, maintainer, site admin, everything but the web designer and I've done it so for not specifying these settings in more places.
    I have the same role in my situation, but I also designed the project so it is
    easier for someone else to come along and maintain it.
    Is there another place where I could put these settings for a certain DBIC schema?
    For example, can I put them in the MyApp/Schema.pm, orsomewhere else? Can you give an example?
    I can show you a simplified version of what I have done, but with any
    identifying details changed to protect the innocent. My version uses straight
    DBI+DBIx::Connector rather than DBIC but you should be able to adapt the design
    to DBIC or any other database API; my version is also Pg-specific but only minor
    tweaks would be needed to work with something else. Since this is from a
    proprietary application rather than a CPAN module, I can get away with requiring
    and exploiting the latest Perl version, 5.12.x, rather than giving those up to
    support older Perls.

    1. Here is the relevant portion of MyApp.conf, which uses Config::General as
    per Catalyst's default these days.

    <Model DB>
    <args>
    db_host localhost
    db_port 5444
    db_name myproj_v1_db
    db_user myproj_v1_usr_myapp
    db_pass myapppass
    </args>
    </Model>

    2. Here is the slightly simplified version of MyApp/Model/DB.pm, which uses
    Catalyst::Model::Adaptor, and in such a way to support different class and file
    names (requires 0.09+):

    use 5.012002;
    use utf8;
    use warnings FATAL => 'all';

    use MyDBMSLib 0.001;

    package MyApp::Model::DB 0.001;

    use parent 'Catalyst::Model::Adaptor'; # requires >= 0.09

    __PACKAGE__->config( class => 'MyDBMSLib' );

    1;

    3. Here is a complete/template content of MyDBMSLib.pm; the original had
    multiple classes in it but I removed the other ones and simplified the main one;
    the original file was named after a different package than what I kept:

    use 5.012002;
    use utf8;
    use warnings FATAL => 'all';

    use DBIx::Connector;
    use DBI;
    use DBD::Pg;

    ###########################################################################
    ###########################################################################

    { package MyDBMSLib 0.001; # class

    use namespace::autoclean;

    use Try::Tiny;

    use Moose;

    has 'db_host' => (is => 'ro', isa => 'Str', required => 1 );
    has 'db_port' => (is => 'ro', isa => 'Int', required => 1 );
    has 'db_name' => (is => 'ro', isa => 'Str', required => 1 );
    has 'db_user' => (is => 'ro', isa => 'Str', required => 1 );
    has 'db_pass' => (is => 'ro', isa => 'Str', required => 1 );

    # This is the actual (as far as we're concerned) Pg database connection
    # object; the connection is opened the first time the _dbc attr is read
    # and it is closed when the _dbc attr is garbage collected.
    has '_dbc' => (
    is => 'ro',
    isa => 'DBIx::Connector',
    required => 1,
    lazy => 1,
    default => \&_lazy_default_for_dbc,
    );

    ###########################################################################

    sub _lazy_default_for_dbc {
    my ($process) = @_;
    my $dbc = try {
    my $dsn = sprintf( q{dbi:Pg:dbname=%s;host=%s;port=%s},
    $process->db_name(), $process->db_host(), $process->db_port() );
    my $dbc = DBIx::Connector->new( $dsn,
    $process->db_user(), $process->db_pass(),
    { 'RaiseError' => 1, 'AutoCommit' => 1 },
    );
    my $dbh = $dbc->dbh();
    # SET UP ANY OTHER CLIENT SETTINGS HERE ON $dbh
    return $dbc;
    }
    catch {
    confess sprintf( q{Could not open connection to Pg server or db:
    %s}, $_ );
    };
    return $dbc;
    }

    ###########################################################################

    # PUT OTHER USEFUL MyDBMSLib METHODS HERE

    ###########################################################################

    __PACKAGE__->meta()->make_immutable();

    } # class MyDBMSLib

    ###########################################################################
    ###########################################################################

    1;

    For your version, mainly just replace _dbc with an object of whatever initial
    class you have with DBIC that takes the db connection config args.

    Your analogy to _lazy_default_for_dbc is where you feed DBIC its actual config
    args, where some can be defined in MyDBMSLib itself and others taken from the
    config file.

    -- Darren Duncan
  • Darren Duncan at Nov 8, 2010 at 8:18 pm

    Darren Duncan wrote:
    sub _lazy_default_for_dbc {
    my ($process) = @_;
    my $dbc = try {
    my $dsn = sprintf( q{dbi:Pg:dbname=%s;host=%s;port=%s},
    $process->db_name(), $process->db_host(),
    $process->db_port() );
    my $dbc = DBIx::Connector->new( $dsn,
    $process->db_user(), $process->db_pass(),
    { 'RaiseError' => 1, 'AutoCommit' => 1 },
    );
    my $dbh = $dbc->dbh();
    # SET UP ANY OTHER CLIENT SETTINGS HERE ON $dbh
    return $dbc;
    }
    catch {
    confess sprintf( q{Could not open connection to Pg server or
    db: %s}, $_ );
    };
    return $dbc;
    }
    As an addendum ...

    While this isn't relevant to the main point of my post, which is how to separate
    config params for a database connection used by a Catalyst app, I noticed that
    my code had a different flaw, which is now hopefully corrected in the version below:

    sub _lazy_default_for_dbc {
    my ($process) = @_;
    my $dbc = try {
    my $dsn = sprintf( q{dbi:Pg:dbname=%s;host=%s;port=%s},
    $process->db_name(), $process->db_host(), $process->db_port() );
    my $dbc = DBIx::Connector->new( $dsn,
    $process->db_user(), $process->db_pass(), {
    RaiseError => 1,
    AutoCommit => 1,
    Callbacks => {
    connected => sub {
    my ($dbh) = @_;
    $process->_do_post_connect( $dbh );
    },
    },
    },
    );
    return $dbc;
    }
    catch {
    confess sprintf( q{Could not open connection to Pg server or db:
    %s}, $_ );
    };
    return $dbc;
    }

    sub _do_post_connect {
    my ($process, $dbh) = @_;
    # SET UP ANY OTHER CLIENT SETTINGS HERE ON $dbh
    }

    The flaw is that if DBIx::Connector had to reconnect to the database, an event
    that users shouldn't have to be aware of having occurred, the client settings
    done by "SET UP ..." would not have been done on the new connection.

    -- Darren Duncan
  • Mike Raynham at Nov 6, 2010 at 5:16 pm

    On 05/11/10 16:50, Darren Duncan wrote:
    Mike Raynham wrote:
    Here, the connection information is moved from MyApp::Model::DB to
    MyApp::DB, and then Catalyst::Model::Adaptor is used to glue
    MyApp::Model::DB to MyApp::DB. Is it a good idea? MyApp::Model::DB
    appears to be part of the Catalyst application, so if I want to access
    the database from an external model, it makes sense to me to move the
    connection code outside of the Catalyst application.
    What you want to do is turn all the stuff that mediates access to the
    database into your own shared library formatted kind of like one you
    might find as a CPAN module, say "MyDBLib", and then "use" it in your
    Catalyst application by way of Catalyst::Model::Adaptor.

    For any configuration details that might vary either per application or
    per deployment, make these user-configurable parameters of MyDBLib, with
    then each of your applications would supply arguments to it when
    instantiating a MyDBLib object; in the Catalyst app's case, said
    arguments would be in your Catalyst app config file as is normal for
    MyApp::Model::DB.

    For any configuration details that are unlikely to vary per application
    or per deployment, especially if they are details for which your actual
    code would vary, then put these directly in your MyDBLib code instead.

    Octavian Rasnita wrote:
    The best idea would be to put the connection information in the
    application's config file like in the example below. (This example
    uses a Perl data structure, but you can use any configuration type
    accepted by Config::Any).

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    dsn => 'dbi:Oracle:host.10.10.10;port21;sid=ora8',
    user => 'user',
    password => "password",
    #name_sep => '.',
    LongReadLen => 100*1024*1024,
    LongTruncOk => 1,
    on_connect_call => 'datetime_setup',
    on_connect_do => [
    "alter session set NLS_COMP='LINGUISTIC'",
    "alter session set NLS_SORT='BINARY_AI'",
    ],
    },
    },

    The model will access the connection information directly if it is
    defined in the config file, and you can use the data from this config
    file in any other external program.
    You can use the module Config::JFDI for using the Catalyst config file
    easier.
    Now some of this looks wrong to me; a lot of those details should be in
    your MyDBLib code instead of the config file. Your config file should
    instead look more like this:

    'Model::DB' => {
    schema_class => 'MyApp::Schema',
    connect_info => {
    host => '10.10.10.10',
    port => 1521,
    user => 'user',
    password => "password",
    },
    },

    These are more details that a non-programmer user would set.

    The other details should all be in your code instead, because users
    shouldn't have to know and in particular if they are changed your code
    could break. In particular I'm thinking of stuff like "on_connect_call"
    or the fact you are using "dbi:Oracle".

    Where it can get fuzzier is if your application is cross-DBMS portable,
    in which case more info would need to be in the config file, but you'd
    want to abstract it somehow, such as users just naming the DBMS and then
    they are actually picking from a pre-defined profile which has the
    code-specific details. But if the app isn't supposed to be portable, eg
    if it uses Oracle-specific stuff, then don't put dbi:Oracle and NLS* and
    that stuff in your user config file.

    Stuff like LongReadLen might be okay here if and only if changing it
    just tunes performance, like you were setting a chunk-buffer size or
    something, and would have no impact on behavior nor break any code;
    otherwise don't have it here.

    -- Darren Duncan
    Hi,

    Thanks for the responses. This is all part of a fairly steep learning
    curve for me. I have tried to keep things fairly simple, but I also
    wanted to experiment with Moose classes...

    My database connection details are very simple, consisting of just the
    dsn, user and password. I have placed these, along with the
    schema_class, in myapp.conf. I can access these details from both the
    Catalyst app, and my external model. To help with that, I have written
    two simple singleton classes using Moose:

    MyApp::Config
    Finds the MyApp.conf file, loads it using Config::Any, and returns it as
    a hash.

    MyApp::DB
    Gets the application config from MyApp::Config and uses the Model::DB
    parameters to connect to CHHC::Schema, and return a DBIx::Class::Schema
    object.

    Components in my external model can now just use MyApp::DB to obtain a
    connection to the schema. I'm sure that there is plenty of room for
    improvement, but so far, it works well and leaves the Catalyst app
    untouched.


    Regards,

    Mike

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedNov 5, '10 at 9:37a
activeNov 8, '10 at 8:18p
posts10
users5
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2021 Grokbase