—package
Mojolicious::Plugin::Model;
use
Mojo::Loader ();
our
$VERSION
=
'0.13'
;
sub
register {
my
(
$plugin
,
$app
,
$conf
) =
@_
;
# check if need camelize moniker
my
$moniker
= camelize(
$app
->moniker);
$moniker
=
$app
->moniker
unless
-d
$app
->home .
'/lib/'
.
$moniker
;
$app
->helper(
model
=>
sub
{
my
(
$self
,
$name
) =
@_
;
$name
//=
$conf
->{
default
};
my
$model
;
return
$model
if
$model
=
$plugin
->{models}{
$name
};
my
$class
= _load_class_for_name(
$plugin
,
$app
,
$conf
,
$name
,
$moniker
)
or
return
undef
;
my
$params
=
$conf
->{params}{
$name
};
$model
=
$class
->new(
ref
$params
eq
'HASH'
?
%$params
: (),
app
=>
$app
);
$plugin
->{models}{
$name
} =
$model
;
return
$model
;
}
);
$app
->helper(
entity
=>
sub
{
my
(
$self
,
$name
) =
@_
;
$name
//=
$conf
->{
default
};
my
$class
= _load_class_for_name(
$plugin
,
$app
,
$conf
,
$name
,
$moniker
)
or
return
undef
;
my
$params
=
$conf
->{params}{
$name
};
return
$class
->new(
ref
$params
eq
'HASH'
?
%$params
: (),
app
=>
$app
);
}
);
}
sub
_load_class {
my
$class
=
shift
;
my
$error
= Mojo::Loader->can(
'new'
) ? Mojo::Loader->new->load(
$class
) : Mojo::Loader::load_class(
$class
);
return
1
unless
$error
;
die
$error
if
ref
$error
;
return
;
}
sub
_load_class_for_name {
my
(
$plugin
,
$app
,
$conf
,
$name
,
$moniker
) =
@_
;
return
$plugin
->{classes_loaded}{
$name
}
if
$plugin
->{classes_loaded}{
$name
};
my
$ns
=
$conf
->{namespaces} // [
$moniker
.
'::Model'
];
my
$base
=
$conf
->{base_classes} // [
qw(MojoX::Model)
];
$name
= camelize(
$name
)
if
$name
=~ /^[a-z]/;
for
my
$class
(
map
"${_}::$name"
,
@$ns
) {
next
unless
_load_class(
$class
);
unless
( any {
$class
->isa(
$_
) }
@$base
) {
$app
->
log
->debug(
qq[Class "$class" is not a model]
);
next
;
}
$plugin
->{classes_loaded}{
$name
} =
$class
;
return
$class
;
}
$app
->
log
->debug(
qq[Model "$name" does not exist]
);
return
undef
;
};
1;
__END__
=encoding utf8
=head1 NAME
Mojolicious::Plugin::Model - Model for Mojolicious applications
=head1 SYNOPSIS
Model Users
package MyApp::Model::Users;
use Mojo::Base 'MojoX::Model';
sub check {
my ($self, $name, $pass) = @_;
# Constant
return int rand 2;
# Or Mojo::Pg
return $self->app->pg->db->query('...')->array->[0];
# Or HTTP check
return $self->app->ua->post($url => json => {user => $name, pass => $pass})
->res->tx->json('/result');
}
1;
Model Users-Client
package MyApp::Model::Users::Client;
use Mojo::Base 'MyApp::Model::User';
sub do {
my ($self) = @_;
}
1;
Mojolicious::Lite application
#!/usr/bin/env perl
use Mojolicious::Lite;
use lib 'lib';
plugin 'Model';
# /?user=sebastian&pass=secr3t
any '/' => sub {
my $c = shift;
my $user = $c->param('user') || '';
my $pass = $c->param('pass') || '';
# client model
my $client = $c->model('users-client');
$client->do();
return $c->render(text => "Welcome $user.") if $c->model('users')->check($user, $pass);
$c->render(text => 'Wrong username or password.');
};
app->start;
All available options
#!/usr/bin/env perl
use Mojolicious::Lite;
plugin Model => {
namespaces => ['MyApp::Model', 'MyApp::CLI::Model'],
base_classes => ['MyApp::Model'],
default => 'MyApp::Model::Pg',
params => {Pg => {uri => 'postgresql://user@/mydb'}}
};
=head1 DESCRIPTION
L<Mojolicious::Plugin::Model> is a Model (M in MVC architecture) for Mojolicious applications. Each
model has an C<app> attribute.
=head1 OPTIONS
L<Mojolicious::Plugin::Model> supports the following options.
=head2 namespaces
# Mojolicious::Lite
plugin Model => {namespaces => ['MyApp::Model']};
Namespace to load models from, defaults to C<$moniker::Model>.
=head2 base_classes
# Mojolicious::Lite
plugin Model => {base_classes => ['MyApp::Model']};
Base classes used to identify models, defaults to L<MojoX::Model>.
=head2 default
# Mojolicious::Lite
plugin Model => {default => 'MyModel'};
any '/' => sub {
my $c = shift();
$c->model->do(); # used model MyModel
# ...
}
The name of the default model to use if the name of the current model not
specified.
=head2 params
# Mojolicious::Lite
plugin Model => {params => {DBI => {dsn => 'dbi:mysql:mydb'}}};
Parameters to be passed to the class constructor of the model.
=head1 HELPERS
L<Mojolicious::Plugin::Model> implements the following helpers.
=head2 model
my $model = $c->model($name);
Load, create and cache a model object with given name. Default class for
model C<camelize($moniker)::Model>. Return C<undef> if model not found.
=head2 entity
my $disposable_model = $c->entity($name);
Create a new model object with given name. Default class for
model C<camelize($moniker)::Model>. Return C<undef> if model not found.
Use C<entity> instead of C<model> when you need stateful objects.
=head1 METHODS
L<Mojolicious::Plugin::Model> inherits all methods from
L<Mojolicious::Plugin> and implements the following new ones.
=head2 register
$plugin->register(Mojolicious->new);
Register plugin in L<Mojolicious> application.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
=head1 AUTHOR
Andrey Khozov, C<avkhozov@googlemail.com>.
=head1 CONTRIBUTORS
Alexey Stavrov, C<logioniz@ya.ru>.
Denis Ibaev, C<dionys@gmail.com>.
Eugen Konkov, C<kes-kes@yandex.ru>.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2017, Andrey Khozov.
This program is free software, you can redistribute it and/or modify it under
the terms of the Artistic License version 2.0.
=cut