Thanks Richard - to be honest I'm not sure why I didn't take advantage of as_tree() - I've been using my dbo2aoh helpers for so many years I got stuck in a rut. Good feedback on the abstraction. I was in a bit of a hurry to knock this one off, and as Winston Churchill said, "I didn't have the time to write you a shorter letter".
Best, Mike. On Thu, Sep 11, 2014 at 2:52 AM, Richard Jones <[email protected]> wrote: > Thanks for the examples Mike. I see you are calling and manipulating your > RBDO classes directly in your routes. That answers my integration question. > I tend to keep all that stuff in separate model classes so that I could > change ORM to say DBIX::Class without any change to the D2 classes. But it > does increase complexity. Just a thought regarding the expansion helpers - > you don't utilise the as_tree() function anywhere? I realise your helpers > do more than just simple object-to-hash conversion. > > my $rv = dbo2h($student); > my $rv = $student->as_tree; > my $rv = $student->as_tree(deflate => 0); # to keep eg DateTime objects > > On 10/09/2014 21:00, Mike Schroeder wrote: > > 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]> > 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 >> [email protected]http://lists.preshweb.co.uk/mailman/listinfo/dancer-users >> >> >> -- >> Richard Jones >> >> >> _______________________________________________ >> dancer-users mailing list >> [email protected] >> http://lists.preshweb.co.uk/mailman/listinfo/dancer-users >> >> > > > _______________________________________________ > dancer-users mailing > [email protected]http://lists.preshweb.co.uk/mailman/listinfo/dancer-users > > > -- > Richard Jones > > > _______________________________________________ > dancer-users mailing list > [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
