How can I use Dancer2::Plugin::Database when my code is split into multiple files?

感情迁移 提交于 2019-12-08 00:59:41

问题


All code examples I have seen related to Dancer2 and database connections put all Dancer2 code directly in the anonymous subroutines attached to the various 'get' and 'put' requests.

I would like to organize my code in a way that myServices.pm file is essentially just a router to the other code files that contain the meat of what is executing. I can successfully use the params keyword in the MyServices::Submission module. However, I can't seem to use the database keyword from Dancer2::Plugin::Database in this context.

myServices.pm:

package myServices;

use Dancer2;
use Dancer2::Plugin::REST;
use Dancer2::Plugin::Database;
use Data::Dumper;
use MyServices::Submission;

get '/direct' => sub {
    my $dbh = database;
    return 'success';
};

get '/indirect' => sub {
   MyServices::Submission::databaseTest();
};

true;

MyServices/Submission.pm:

package MyServices::Submission;

use Dancer2;
use Dancer2::Plugin::REST;
use Dancer2::Plugin::Database;
use Data::Dumper;


sub databaseTest{
    my $dbh = database;
    return 'success';
}

true;

The call to /direct returns 'success'.
The call to /indirect returns Error 500 - Internal Server Error with the message "Can't get a database connection without settings supplied!". It then prints out my settings, including the correct database configuration.

My configuration file must be fine, because the call to /direct is a success.

Q's:

  1. Can anyone else replicate this behavior? (Make sure I'm not missing something obvious.)
  2. Is there a way to successfully use Dancer2::Plugin::Database in the MyServices::Submission module, or do I need to search for another db connection solution in order to meet my code organization needs?

回答1:


When you call use Dancer2; in MyServices::Submission, you're actually creating a separate Dancer2 app:

As soon as you import Dancer2 (by calling use Dancer2), you create a Dancer2 App. It will use your class name (defined by either the package function in Perl or the default in Perl: main) to define the Dancer2 App name. This is how Dancer2 will recognize your application.

This introduces an interesting situation. If you wish to separate your App to multiple files, you're actually creating multiple applications.

So what?

This means that any engine defined in an application, because the application is a complete separate scope, will not be available to a different application:

package MyApp::User {
      use Dancer2;
      set serializer => 'JSON';
      get '/view' => sub {...};
 }

package MyApp::User::Edit {
     use Dancer2;
     get '/edit' => sub {...};
 }

These are two different Dancer2 Apps. They have different scopes, contexts, and thus different engines. While MyApp::User has a serializer (the JSON one) defined, MyApp::User::Edit will not have that configuration.


You can use the appname option when you import Dancer2 to say that your module should extend an app instead of creating a new one:

package MyServices::Submission;

use Dancer2 appname => 'MyApp';
use Dancer2::Plugin::Database;

sub databaseTest {
    my $dbh = database;                                 
    return 'success';
}

1;

Now the configuration and engines from the main app will be available inside MyServices::Submission. You can even add additional routes here.


As an aside, splitting up your application like this is a great idea; if you're interested in other techniques, someone on the Dancer users mailing list wrote up some pretty thorough recommendations on how to organize medium- to large-scale Dancer applications. The recommendations are split into six parts; see here for the full listing.



来源:https://stackoverflow.com/questions/37012789/how-can-i-use-dancer2plugindatabase-when-my-code-is-split-into-multiple-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!