Skip to content

Instantly share code, notes, and snippets.

@ynonp
Created September 12, 2012 12:47
Show Gist options
  • Save ynonp/3706374 to your computer and use it in GitHub Desktop.
Save ynonp/3706374 to your computer and use it in GitHub Desktop.
Dancer Crud
[% BLOCK text_field %]
<div class="control-group">
<label for="inp-name">[% data.key %]</label>
<div class="control">
<input type="text" id="inp-[% data.key %]" name="[% data.key %]" value="[% data.value %]"/>
<span class="help-inline">שדה חובה</span>
</div>
</div>
[% END %]
[% BLOCK textarea_field %]
<div class="control-group">
<label for="inp-description">[% data.key %]</label>
<div class="control">
<textarea id="inp-[% data.key %]" name="[% data.key %]">[% data.value %]</textarea>
<span class="help-inline">שדה חובה</span>
</div>
</div>
[% END %]
[% BLOCK select_field %]
<div class="control-group">
<label for="inp-[% data.key %]">[% data.key %]</label>
<select name="[% data.key %]">
[% FOREACH o IN data.options %]
[% IF ( o == data.value ) %]
<option value="[% o %]" selected="selected">[% o %]</option>
[% ELSE %]
<option value="[% o %]">[% o %]</option>
[% END %]
[% END %]
</select>
</div>
[% END %]
[% BLOCK number_field %]
<div class="control-group">
<label for="inp-[% data.key %]">[% data.key %]</label>
<input type="number" id="inp-[% data.key %]" name="[% data.key %]" value="[% data.value %]" />
</div>
[% END %]
[% BLOCK checkbox_field %]
<div class="control-group">
<label for="inp-[% data.key %]">[% data.key %]</label>
<input type="CHECKBOX" [% data.value ? 'checked="checked"' : '' %] name="[% data.key %]" value="1" />
</div>
[% END %]
[% BLOCK skip_field %]
[% END %]
<form method="POST" action="[% admin_url %]">
[% FOREACH att IN attributes %]
[% INCLUDE $att.type data=att %]
[% END %]
<div class="control-group">
<input type="submit" value="שמור" class="btn btn-primary"/>
</div>
</form>
use true;
use v5.14;
use warnings;
{
package YPCourse::Meta::Serializable;
use Moose::Role;
has 'in_db', default => 0, is => 'ro', isa => 'Bool';
has 'form_opts', is => 'ro', isa => 'HashRef', default => sub { {} };
}
{
package YPCourse::Roles::Storable;
use Moose::Role;
use Moose::Exporter;
use Readonly;
use Dancer qw/:moose/;
use Hash::Merge qw/merge/;
use Lingua::EN::Inflect qw/PL/;
use Dancer::Plugin::Mongo;
use MongoDB;
requires 'blank';
has '_id', is => 'ro', isa => 'MongoDB::OID', predicate => 'loaded_from_db';
has 'admin_url', is => 'ro', isa => 'Str', lazy_build => 1;
has 'order', isa => 'Int', default => 99, in_db => 1, is => 'ro',
form_opts => { type => 'number_field' }, traits => [qw/YPCourse::Meta::Serializable/];
sub collection_name {
my $self = shift;
my ( $name ) = $self->meta->name =~ /::(\w+)$/;
return PL( lc($name) );
}
sub _build_admin_url {
my $self = shift;
"/admin/" . $self->collection_name . '/';
}
sub id {
my $self = shift;
return $self->_id->value;
}
sub form_for {
my ( $self, $action ) = @_;
my $attribtues_db = $self->to_db;
my $attributes = [];
while ( my ($k, $v) = each $attribtues_db ) {
my $att = $self->meta->get_attribute($k);
if ( ! $att->does('YPCourse::Meta::Serializable') ) {
next;
}
my $opts = $att->form_opts;
my $next = { key => $k, value => $v, type => 'skip_field' };
push $attributes, merge($opts, $next);
}
template('admin/form', {
attributes => $attributes,
admin_url => $self->admin_url . ( $action eq 'new' ? 'add' : $self->id ),
},
{ layout => undef } );
}
sub new_form_for { shift->form_for('new') }
sub edit_form_for { shift->form_for('edit') }
sub to_db {
my $self = shift;
my $obj = {};
foreach my $att ( $self->meta->get_all_attributes ) {
if ( $att->does('YPCourse::Meta::Serializable') && $att->in_db ) {
my $name = $att->name;
my $reader = $att->get_read_method;
my $val = $self->$reader;
$obj->{$name} = $val;
}
}
if ( $self->loaded_from_db ) {
$obj->{_id} = MongoDB::OID->new( value => $self->_id->value );
}
return $obj;
}
sub create_routes {
my $self = shift;
my $collection = $self->collection_name;
get "/admin/$collection" => sub {
template "admin/$collection",
{
$collection => [ sort { $a->order <=> $b->order }
map { $self->meta->new_object( $_ ) }
mongo->mobileweb->get_collection($collection)->find->all ],
blank => $self->blank,
};
};
post "/admin/$collection/add" => sub {
my $params = params();
my $item = $self->meta->new_object( $params );
mongo->mobileweb->get_collection($collection)->insert( $item->to_db );
template "admin/$collection";
};
post "/admin/$collection/delete/:cid" => sub {
my $params = params();
my $id = param 'cid';
my $mid = MongoDB::OID->new( value => $id );
mongo->mobileweb->get_collection($collection)->remove({_id => $mid});
};
post "/admin/$collection/:cid" => sub {
my $params = params();
my $id = param 'cid';
my $mid = MongoDB::OID->new( value => $id );
my $new_item = $self->meta->new_object( $params );
use Data::Dumper;
debug Dumper($new_item);
mongo->mobileweb->get_collection($collection)->update( {_id => $mid }, $new_item->to_db );
redirect "/admin/$collection";
};
}
Moose::Exporter->setup_import_methods(
also => 'Moose',
class_metaroles => {
attribute => ['YPCourse::Meta::Serializable']
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment