Hi Richard - not sure mine is the most elegant approach vis a vi
plugins - but it is working, and it is fast :) For production I'm
running multiple instances of Dancer with shared memcached for session
management, all behind balance. This is all on a 12-core OS X
Mavericks box and barely makes a blip on utilization.
1) I generated all the Rose::DB::Object classes from the MySQL schema
for the RDBO classes and Manager classes.
2) I wrote a few helper functions to convert DBO objects in hash or
array of hash suitable for Dancer templating (I'll copy those in
below). I still use HTML::Template over TT just so that I can have
non-coder HTML designers work with the templates, so these data
structures work for that template engine. The result is a route that
looks like this:
#----------------------------------------------------------------------
get '/modal/points/:student_id' => sub {
#----------------------------------------------------------------------
my $student = NDB::Student->new( id => params->{student_id} )->load;
my $rv = dbo2h($student);
template "staff/modal/points", $rv, {layout => "simple"};
};
Here are a few other sample routes:
#----------------------------------------------------------------------
post '/studio' => sub {
#----------------------------------------------------------------------
my @fields = ( qw( studio_name campus_id location session_rate
calendar_id ) );
dbo_add_update("NDB::Studio", { params }, \@fields );
redirect "/admin/campus";
};
#----------------------------------------------------------------------
post '/studio/delete' => sub {
#----------------------------------------------------------------------
my $p = NDB::Studio->new( id => params->{id} );
if ( params->{id} == params->{confirm_id} ) {
$p->delete;
}
redirect "/admin/campus";
};
I also have some other helpers that follow RDBO relationships and
inflate the data structures for templating:
#----------------------------------------------------------------------
get '/campus' => sub {
#----------------------------------------------------------------------
my $campuses = NDB::Campus::Manager->get_campus();
my $rv = dbom2aoh( $campuses, { studios => 'studio_list', staff
=> 'staff_list', } );
template "admin/campus", { campus_list => $rv, add_navbar() }, {
layout => 'staff'};
};
3) The helper functions help glue Dancer and RDBO together:
=head2 dbo2h()
dbo2h - convert a DBO object into a hash of key/value pairs.
my $hashref = dbo2h( $dboobject, $date_format_string, $expandhash,
$prepend );
=cut
sub dbo2h {
my $row = shift;
my $date_format = shift || '%Y-%m-%d %T';
my $expand = shift;
my $prepend = shift;
my $parent_prepend = shift;
my %hash = $row->column_value_pairs;
foreach my $key ( keys %$expand ) {
my $reln = $expand->{$key};
if ( $prepend ) {
$hash{$reln . '_' . $key} = ( $row->$reln ? $row->$reln->$key
: '' );
} else {
$hash{$key} = ( $row->$reln ? $row->$reln->$key : '');
}
}
foreach my $key ( keys %hash ) {
if ( ref $hash{$key} eq 'DateTime' ) {
$hash{$key} = $hash{$key}->strftime($date_format);
}
elsif ( ref $hash{$key} eq 'Time::Clock' ) {
$hash{$key} = $hash{$key}->as_string;
}
$hash{$key} =~ s/\s+$//g;
if ( $parent_prepend ) {
$hash{$parent_prepend.'_'.$key} = delete $hash{$key};
}
}
return \%hash;
}
=head2 dbo2aoh()
dbo2aoh - convert a DBO set of objects into an array of hash of
key/value pairs.
my $arrayref = dbo2aoh( $dboarray, $date_format_string,
$expandhash, $prepend );
=cut
sub dbo2aoh {
my $rows = shift;
my $date_format = shift;
my $expandhash = shift;
my $prepend = shift;
my $parent_prepend = shift;
my @results;
foreach my $row ( @$rows ) {
push(@results, dbo2h( $row, $date_format, $expandhash, $prepend,
$parent_prepend ) );
}
return \@results;
}
=head2 dbo_add_update()
dbo_add_update - convert Dancer params into DBO add/update
my @fields = ( qw( field1 field2 field3 ) );
@errors = dbo_update( 'NDB::Lecture', { params }, \@fields, );
=cut
sub dbo_add_update {
my ( $class, $p, $fields ) = @_;
my ( $obj, @errors );
if ( $p->{id} ) {
$obj = $class->new( id => $p->{id} );
push(@errors, "No such record") unless $obj->load_speculative;
unless ( @errors ) {
foreach my $field ( @$fields ) {
$obj->$field( $p->{$field} ) if exists $p->{$field};
}
$obj->save;
}
} else {
my %columns;
foreach my $field ( @$fields ) {
$columns{$field} = $p->{$field} if exists $p->{$field};
}
$obj = $class->new( %columns );
$obj->save;
}
return $obj;
}
=head2 dbom2aoh()
dbom2row - convert dbo to AOH and add DBOM relationships as child AOH
$rv = dbo_update( $dbo, { relationship => 'hash_key' },
$date_format_string, $expandhash, $prepend );
=cut
sub dbom2aoh {
my ( $parent, $map, $dateformat, $expand, $prepend ) = @_;
my @rv;
foreach my $dbo ( @$parent ) {
my $row = dbo2h( $dbo, $dateformat, $expand, $prepend );
foreach my $reln ( keys %$map ) {
my $children = $dbo->$reln;
$row->{ $map->{$reln} } = dbo2aoh( $children, $dateformat );
}
push @rv, $row;
}
return \@rv;
}
Like I said in my initial post - I'm sure there are refactor
opportunities in my code - so please be kind :) I tried to go for
readability over conciseness so that I could hand it off at some point.
Hope that helps.
Best,
Mike.
On Wed, Sep 10, 2014 at 12:19 PM, Richard Jones
<[email protected] <mailto:[email protected]>> wrote:
Hello Mike,
I was very interested to read about your experience. I'm not
touting for the job as I have a full-time job already. But just to
say I'm a recent convert to Dancer2 from developing long-term with
CGI::Application/RBDO/MySQL. I'm most interested in how you
integrated Rose with Dancer. I haven't tried it yet as all my
recent apps are small enough to use DBIx::Simple, but I'm planning
a bigger one that will need an ORM. Do you use the MVC
architecture? Do you use an adapter class for Rose or just rely on
the Dancer DB plugin? Is your project open source or are you not
able to expose the code base publicly?
Good luck recruiting.
On 10/09/2014 19:39, Mike Schroeder wrote:
Hi all - I've been using Dancer for years and have watched this
list for years - thank you to everyone for a great framework.
In my new role at a new company (an audio engineering and
production school), I searched for an off the shelf system to do
what I wanted, and finally gave up and wrote my own. Dancer,
Rose::DB::Object, Bootstrap and MySQL - amazing what you can do
in 3-4 months of spare time :)
The project is up and in production, running well, and now we are
wanting to add more features, etc. I am too busy doing my real
job (CEO) to have the time to do the development work on the system.
I'm looking for someone who can can SSH into our servers from
anywhere, work within my existing architecture to extend and add
features, refactor some of my prototype code (it's not horrible,
but I know it could be better), and help move the project forward.
The ideal candidate would have experience with Dancer,
Rose::DB::Object, Bootstrap and MySQL. There is also a POE-based
daemon using Rose::DB::Object running alongside for long-running
asynchronous job handling, so POE experience would be helpful as
well.
This is not a full-time job - more project based work to add new
features, etc. I expect to keep building this out over the next
year, so I'm looking for a good long term partner to work with.
I'm ok with different timezones, as long as we can find some
common time for Skype etc. (I'm in Vancouver, so Pacific Timezone).
If you are interested, you can send an email to mike at
nimbusrecording dot com. Let me know your experience and
expectations for payment.
Thanks all - I really appreciate the Dancer community and what it
allows us all to create.
Best,
Mike.
_______________________________________________
dancer-users mailing list
[email protected] <mailto:[email protected]>
http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
--
Richard Jones
_______________________________________________
dancer-users mailing list
[email protected] <mailto:[email protected]>
http://lists.preshweb.co.uk/mailman/listinfo/dancer-users
_______________________________________________
dancer-users mailing list
[email protected]
http://lists.preshweb.co.uk/mailman/listinfo/dancer-users