Mura ORM & Ember JS

Post on 08-May-2015

355 views 0 download

description

Originally presented by Matt Levine at MuraCon EU 2014 in Edinburgh, Scotland.

Transcript of Mura ORM & Ember JS

Mura ORM and EmberJS• By Matt Levine

Who Am I?

Who Am I?• CTO of Blue River Interactive Group

Who Am I?• CTO of Blue River Interactive Group• Started Mura CMS with Sean Schoeder a long time

ago...

What We’re Talking About

What We’re Talking About• Mura ORM

What We’re Talking About• Mura ORM• EmberJS

What We’re Talking About• Mura ORM• EmberJS• But Mostly Mura ORM

Why Mura ORM?

Why Mura ORM?• It all started with creating the Mura approval chains.

Why Mura ORM?• It all started with creating the new Mura approval

chains.• Needed to create 5 new entities and didn’t want to

write a custom DAO for each one.

Started with 3 Options

Started with 3 Options• Custom DAOs

Custom DAOs• Too much work

Custom DAOs• Too much work• No code re-use

Started with 3 Options• Custom DAOs• Mura Class Extension Module

Mura Class Extension ModuleGREAT FOR:

• Targeting nodes for custom business logic

Mura Class Extension ModuleGREAT FOR:

• Targeting nodes for custom business logic• Rendering events

Mura Class Extension ModuleGREAT FOR:

• Targeting nodes for custom business logic• Rendering events• Data events

Mura Class Extension ModuleGREAT FOR:

• Targeting nodes for custom business logic• Rendering events• Data events• Adding custom values to be used within rendering and

data events

Mura Class Extension ModuleNOT AS GOOD FOR:

• Maintaining relationships between entities

Mura Class Extension ModuleNOT AS GOOD FOR:

• Maintaining relationships between entities• Really custom business logic

Mura Class Extension ModuleNOT AS GOOD FOR:

• Maintaining relationships between entities• Really custom business logic• Directly querying the database

Mura Class Extension ModuleRECAP:

• Only handles very simple entities

Mura Class Extension ModuleRECAP:

• Only handles very simple entities• Great for hooking attributes to existing Mura entities, but

bad for complicated logic.

Mura Class Extension ModuleRECAP:

• Only handles very simple entities• Great for hooking attributes to existing Mura entities, but

bad for complicated logic.• Want the data to be stored in flat tables.

Mura Class Extension ModuleRECAP:

• Only handles very simple entities• Great for hooking attributes to existing Mura entities, but

bad for complicated logic.• Want the data to be stored in flat tables.• Not the appropriate choice

Started with 3 Options• Custom DAOs• Mura Class Extension Module• CF based Hibernate ORM

CF Hibernate ORMGREAT FOR:•Easily defining entity properties

CF Hibernate ORMGREAT FOR:•Easily defining entity properties•CRUD operations

CF Hibernate ORMGREAT FOR:•Easily defining entity properties•CRUD operations•Managing relationships to other CF ORM entities

CF Hibernate ORMGREAT FOR:•Easily defining entity properties•CRUD operations•Managing relationships to other CF ORM entities•You just describe the entity with properties and start

using it!

CF Hibernate ORMNOT SO GOOD FOR:•Creating relationships to Mura core entites

CF Hibernate ORMNOT SO GOOD FOR:•Creating relationships to Mura core entites•Working with DI1

CF Hibernate ORMNOT SO GOOD FOR:•Creating relationships to Mura core entites•Working with DI1•Don’t want to deal with sharing hibernate sessions with

other application and plugins

CF Hibernate ORMNOT SO GOOD FOR:•Creating relationships to Mura core entites•Working with DI1•Don’t want to deal with sharing hibernate sessions with

other application and plugins• It just works, but when it doesn't... Good Luck

CF Hibernate ORMRECAP:•Love the concept!

CF Hibernate ORMRECAP:•Love the concept!•Seems like CF ORM would be a walled garden.

CF Hibernate ORMRECAP:•Love the concept!•Seems like CF ORM would be a walled garden.•Sharing a ORM session with other sub applications

sounds like a nightmare

CF Hibernate ORMRECAP:•Love the concept!•Seems like CF ORM would be a walled garden.•Sharing a ORM session with other sub applications

sounds like a nightmare• I would like the relationships to be based on DI1

BeanName or Alias rather than component path.

CF Hibernate ORMRECAP:•When things go wrong it really feels like a black box. You

get low level java error that don't neccesarilly easily map to what you did wrong in your CFML•CF ORM really seems to want you to forget about sql

and just go through it's black box. I like sql. I think is it's pretty darn cool

What if?

What if?• I roll my own that works exactly how Mura works!

I Could Make Them Accesible via $.getBean(entityName); and application.serviceFactory(entityName);Takes advantage of DI1 dependency injection

Have the Same Interactions• entity.loadBy()• entity.get{relateEntity}Iterator();• entity.get{relateEntity}Query();• entity.get{relateEntity}();• entity.getFeed();• entity.validate();• entity.getError();

Have the Same Interactions• entityFeed.addParam();• entityFeed.getQuery();• entityFeed.getIterator();

Have the Same Interactionsfeed=$.getBean(entityName).getFeed();feed.addParam(column=’mycolumn’,criteria=‘test’);iterator=feed.getIterator();!

<cfloop condition=”iterator.hasNext()”><cfoutput>#iterator.next().getMyColumn()#</cfoutput></cfloop>

Be Targetable By Mura Eventscomponent extends=”mura.cfobject”{

onBeforeMyEntitySave($){var bean=$.event(‘bean’);....

}}

They Could Also• Know how to bundle themselves• Play well with Mura content versioning• Have a more simple implementation than CF ORM

It could use the same component attributes

• entityName• table• datasource• discriminatorColumn• discriminatorValue

• orderby• readonly

With some new ones• bundleable• cacheName• dbtype• manageSchema• useTrash

It could use the same property attributes

• name• persistent• fieldtype• cfc• fkcolumn

• type• cascade• singularName• orderby• length

• default• ormType

!

!

With some new ones• dataType• nullable• required• validate• message

• regex• comparable

And a bunch attributes for validation

• minValue• maxValue• minLength• maxLength• minCollection

• maxCollection• minList• maxList• inList• method

• lte• lt• gte• gt• eq

• neq

It could also support CF ORM • preLoad();• postLoad();• preUpdate();• postUpdate();• preCreate();

• postCreate();• postInsert();• preDelete();• postDelete();

So that’s what we did

So that’s what we did• Now let’s actually see some code

EmberJS

EmberJS• A Framework for Creating Ambitious Web Applications

EmberJS• A Framework for Creating Ambitious Web Applications• A Client Side MVC Framework

EmberJS• A Framework for Creating Ambitious Web Applications• A Client Side MVC Framework• That’s opinionated in a good way

EmberJS• A Framework for Creating Ambitious Web Applications• A Client Side MVC Framework• That’s opinionated in a good way• So that your application is developed in a consistent

way which enables easier scalability

EmberJS• A Framework for Creating Ambitious Web Applications• A Client Side MVC Framework• That’s opinionated in a good way• So that your application is developed in a consistent

way which enables easier scalability• Utilizes Handlebars.js for easy templating

Handlebar.JS<div> <label>Name:</label> {{input type="text" value=name placeholder="Enter your name"}}</div><div class="text"><h1>My name is {{name}} and I want to learn Ember!</h1></div>

Ember-Data•A Data Persistence Library for Ember.js

Ember-Data•A Data Persistence Library for Ember.js•We’ve created a Mura ORM Adapter for Ember-Data

Ember-Data•A Data Persistence Library for Ember.js•We’ve created a Mura ORM Adapter for Ember-Data•Sooo…

Ember-Datacomponent extends="mura.bean.beanORM" entityName="widget" table="widgets" {property name="widgetid" fieldtype=“id";property name="name" type=“string"length="100" required=true message="The name attribute is required an must be.";

property name="options" singularname="option" fieldtype="one-to-many" cfc="option" cascade="delete"; }

Ember-DataApp.Widget = DS.Model.extend({ primaryKey: 'widgetid', widgetid: DS.attr(), siteid: DS.attr(), name: DS.attr(), options: DS.hasMany('Option',{async:true})});

Ember-Datacomponent extends="mura.bean.beanORM" entityName="option" table="widgetoptions" {property name="optionid" fieldtype="id";property name="name" type="string" length="100" required=true message="The name attribute is required an must be.";property name="widget" fieldtype="many-to-one" cfc="widget" fkcolumn="widgetid";}

Ember-DataApp.Option = DS.Model.extend({ primaryKey: 'optionid', optionid: DS.attr(), siteid: DS.attr(), name: DS.attr(), widgetid: DS.attr(), widget: DS.belongsTo('Widget',{async:true})});

Ember-DataApp.WidgetRoute = Ember.Route.extend({ model: function(params) { return this.store.find(‘Widget’,params.widgetid); }});

Ember-Data<script type="text/x-handlebars" id=“widget"><h3>{{name}} ({{options.length}})</h3>{{#if options.length}}<ul>{{#each option in options}} <li>{{option.name}}</li>{{/each}}</ul>{{/if}}</script>

Ember.js•We’re currently prototyping an Ember.js based front for Mura

Ember.js•We’re currently prototyping an Ember.js based front for Mura•It will allow Mura to run as a service

Ember.js•We’re currently prototyping an Ember.js based front for Mura•It will allow Mura to run as a service•This will allow Mura sites to be served locally on any web server without needing a servlet container.

Ember.js•We’re currently prototyping an Ember.js based front for Mura•It will allow Mura to run as a service•This will allow Mura sites to be served locally on any web server without needing a servlet container.•We feel at this point it’s a perfect fit