ORM’s Dreaming Big: pt 2 (The instance)

Before we went over the Schema which is about validation, indexes, population and schematypes. Here we’ll go into what people will be most likely using, the instance. So, what is the instance?

An Instance is

  • Holds values you wish to store or have retrieved
  • Something that can be created, requested, updated and deleted
  • Something that has properties which can match conditions

Basically an instance is the actual values you want to store or retrieve. Probably the most important part about the database as without it, well, you have nothing.

Generic yet Important Things

Callbacks

Callbacks can be implemented in one of two ways; callback(err,obj) or Promises.

Constructor(ObjectId, function(err,instance){
  if(err) throw err;
  console.log("this is our instance", instance);
});

Constructor(ObjectId).next(function(instance){
  console.log("this is our instance", instance); 
}).catch(function(err){
  throw err;
});

This is meant to support anything that you want.

Handles and Values

Instances are technically either an ObjectID handle or the Actual Values. They both have the same interface however with ObjectID’s you do not have to load all of the values nor do you have all of the values. While with an instance you do. This is to support as much IO or as little IO as you desire without having to change the interface.

Creating

Creating an instance should be as simple as creating an object in javascript

Standard – Construct and Save
var instance = new Constructor({
  property:"value"
});
instance.property2 = "value2";

instance.save(function(err){
  if(err) throw new Error("creating caused an error");
  console.log("finshed creating");
});

Now, we haven’t gotten into “Constructors” or “Models” however hopefully this sort of syntax is familiar to you. It’s simple. We want to create a new instance, so we construct it. Because values may be added or removed, the object is not saved right after creating. Additionally, its important that this is done asynchrnously. We don’t know when the file will be saved or how the file will be saved, only that the file will be saved.

Calling the Constructor – Less IO

When all of the values are already in the json object, constructing the object is a waste of time and resources.

Constructor({
  property:"value",
  property2:"value2"
}, function(err,objectid){
  if(err) throw new Error("error when creating");
  console.log("finished creating");
});

You may notice that the standard’s callback has no objectid but the create does. This is because if when you’ve succesfully saved, an ObjectID is already set for you in addition, you already have an interface to interact with the Instance. So there is no point in returning anything. While when using create, it will give you the ObjectID handle to provide you an interface to interact with. However, the handle will not have any properties in it so I would suggest you use instances if you want them.

Static Method – Obvious

In addition,  you may also call the static method. This will return the instance.

Constructor.create({
  property:"value",
  property2:"value2"
}, function(err,instance){
  if(err) throw new Error("error when creating");
  console.log("finished creating");
});

Retrieving

Generally the way retrieving will work is through the Constructors static methods. However, we are going for sugar here.

Standard – ObjectID Populating

If we have an ObjectID Handle, we can populate it into an actual Instance. It’s important to note there is a difference between an ObjectID Value and an ObjectID Handle. The value is the bytes/buffer that actually gets indexed. The ObjectID Handle has all the methods of a normal Instance. Generally all ObjectID Values will be transformed into Instances when retrieving an instance. In addition, anywhere you can use an ObjectID Value you can use an ObjectID Handle

objectidHandle.populate(function(err,instance){
  if(err) throw new Error("error in populating");
  console.log("populated the instance");
});
By ObjectID Value – Opposite
//Retreiving
Constructor(objectidValue,function(err,instance){
  if(err) throw new Error("error in retrieving");
  console.log("retrieved the instance");
});

The above is simple. We use our constructor with the object id and it will return an instance. This is the exact opposite as the initial where we send in some values to create an instance and we receive an objectID handle and this will retreive the instance based on the Handle or Value.

Static Method – Obvious
//Retreiving
Constructor.get(objectidValue,function(err,instance){
  if(err) throw new Error("error in retrieving");
  console.log("retrieved the instance");
});

Updating

Standard – save

With your Constructed/Retrieved Object it is the exact same as it was before, simply save.

//Updating
instance.property = "new value";
instance.save(function(err){
  if(err) throw new Error("updating caused an error");
  console.log("finished");
});
Static Method – Obvious

You may also update just by calling the update method of your constructor

Constructor.update(ObjectId, 
  {property:"new value"},
  function(err, instance){
    if(err) throw new Error("error when using update");
    console.log("ran update");
});

Deleting

Deleting is the last part of our crud interface here. As you might Imagine, it’s more of the same

Standard – destroy
//Updating
instance.destroy(function(err){
  if(err) throw new Error("destroying caused an error");
  console.log("finished");
});
Static Method – Obvious

You may also update just by calling the update method of your constructor

Constructor.destroy(ObjectId, function(err, instance){
    if(err) throw new Error("error when using update");
    console.log("ran update");
});

 Property Setting and Getting

Digestors and Verbose

All properties on an instance are actually getter and setter functions.

Object.defineProperty(instance, "propertyname", {
  get: function(){
    return Schema.propertyname.verbose(
      instance._rawValues.propertyname
    );
  },
  set: function(v){
    var ds = Schema.propertyname.digestors;
    var l = ds.length;
    var vv = void(0);
    for(var i=0;i<l;i++){
      vv = ds[i](v);
      if(typeof vv != "undefined") break;
    }
    if(i===l){
      throw new Error("cannot digest ",v);
    }
    instance._rawValues.propertyname = vv;
  }
});

For the getter we are returning the verbose value. For the Setter, we are digesting the value to its raw type.

Marking Dirty Properties and resetting

The first thing that can be done is to mark dirty properties. This also ties in with the way digesters and getters. In addition when setting, we also set which properties are dirty. This is done so that only the dirty values are actually updated

set: function(v){
    var vv = Schema.property.digest(v);
    if( vv == instance._initvalues.property ){
      delete instance._dirty.property
    }else{
      instance._dirty.property = vv;
    }
    instance._values.property = vv;
   }

Instance.prototype.save = function(cb){
  return Instance.update(this.id,this._dirty,cb);
}

Instance.prototype.reset = function(){
  for(var i in this._dirty){
    if(this._dirty[i]){
      this._dirty[i] = false;
      this._values[i] = this._initvalues[i]
    }
  }
}

 

Resync with the sender

At times you may want to ensure your instance is the exact same as the one on the database or the location that sent you the instance. All that needs to be done is resync

Instance.prototype.resync = function(cb){
  var _this = this;
  Instance(this.id,function(err,values){
    if(err) return cb(err);
    for(var i in values){
      _this[i] = values[i];
    }
    cb(void(0), _this);
  });
}
Listening for Updates

You may also use an event emitter that sends “update” event with property name and value

Instance.prototype.syncTo = function(ee){
  var _this = this
  ee.on("update",function(prop,val){
    _this[prop] = val;
  })
};

Dom and QueryString Interactions

And of course, you will need some dom interactions. Idealy, I would use an available library such as qs and serializeObject and deserialize to ensure I don’t mess up. From there I would properly set either the values in the object or the values in the query string or form. In addition its also possibly to bind the Instance to the form by using syncTo.

That is the instance

Perhaps there is too much sugar here. Perhaps not enough in the right areas. I’ve considered streaming as an alterantive plan however, In the end, I believe a simple API is a good api. Perhaps I should prioritize a bit. What is for sure in is all of the static methods, ObjectID.populate, instance saving, instance destroying and using the Constructor, well as a constructor. In addition, the dom/querystring aspects is pretty important since without it we’re back at square one: A decent ORM with refusal to believe the DOM or urls that don’t use JSON exist. Everything else is a bit up in the air.

Forms, querstrings and Json Objects

I was going to write a long rant on jQuery’s github issues (specifically this one). However, I think I’ve been in the the programming world enough to realize a few things

  • Everyone wants a feature, no one wants to code it
  • Dismissal comes from lack of assertiveness
  • The open source world runs on voluntary slavery 😉

As a result, I don’t blame the guy for dismissing the person so easily. But I also think it’s a bit heart breaking. So much so I was going to write a big angry letter. However, instead of doing it there, I’ll do it here…

jQuery’s interactions with form’s are quite lackluster. They are so bad that in my eyes its a reasonable question why serialize and seralizeArray havn’t been deprecated. A cynical and confrontational perspective would say it’s only there for backwards compatability. But `jQuery(form).serialize()` sticks around for a better reason, it’s an easy to use useful feature to developers. jQuery in fact is not necessary at all, except for the fact: jQuery is easy to use and useful. You don’t have to think up an algorithm, it’s already there. Theres something to be said though that most of these things are just wrappers. And they are, they are just wrappers. However, there is a big difference between an easy to use .width vs an unstandardized implementation of validation. One is a very useful plugin, the other feels like it should have been done this way all along.

QueryString <-> Form

We all know about Jquery’s serialize() function (and if you don’t, it’s useful for submitting a form over ajax) which does it’s job effectively. However, what about deserialize? Theres some interesting history here, in particular I’m going to talk about this repo. About four years ago from today in 2010, the maintainer created a ticket for jQuery. As you can see, it was refused. One could say they have valid arguments. So let’s look at them.

  • Too Large – sitting at 1.4 kb, it is far from large for what it does
  • We don’t need it in core – Is jQuery’s effects needed in core? What about data? It would seem to me that jQuery should be about manipualting the dom in a simple manner
  • Not Used Everyday – This is something that is arguable. Unfortunately I could only come up with one reason since queries are only in urls. Search forms should populate based off the current query. That being said, that is an excellent reason.

JSON Object <-> Form

So who believes that form->Json would be useful?

This “serializeObject” business isn’t just some fad that will go away. It has been a problem for as long as people wanted to interact with the form before it gets submitted. They have tried to circumvent it with serializeArray and this is arguably far more efficient than serializing to a Json Object. However, there starts to arize some issues.

  • The serialized array doesn’t have any of the attributes, as a result you must then make an additional query for the input to see the what validations it has. But at that point you may be better off validating based by querying for inputs.
  • If you are looking for a specific input type, you must iterate over the objects until you find the one with the name you’re looking for. they are most likely in the same order as they were in the dom so you may be able to select it by the number. However, since disabled control’s will not be included the programmer is better off iterating

Now, going one way is possible in plugins and even without them (technically). However, how do you apply a JSON Object as form values? There is no function in jQuery that will do this. However, our deserialize plugin from before kicks ass in another area. This would have far more uses than applying a get query to a from including:

  • Setting defaults to a form
  • Setting the form based off an ajax source
  • Allowing a form to have a two way binding mechanism – this can be used in physics similations where the form would be updated based off the position, velocity, etc. However, updating the form will as a result update the physics.

JSON Object <-> QueryString

If you commonly parse query strings to json objects (which would likely only be used when applying the url to a search), you can use something along the lines of

var formobj = require("querystring")
  .parse(jQuery(form).serialize());

So long as you have browserify or an amd available. This module will also allow you to implement

var windowobj = require("querystring")
  .parse(window.location.search);

However, if you’re going to go down this route, I highly suggest you use qs. The team that backs it is funded by walmart and supports alot more than query string does.

Will change ever come?

The First thing we should ask ourselves is: Why is change necessary? The idea of it being a plugin has not perked enough ears to warrent anyone else to get fussed up over it.

Finding plugin’s waste’s time

Serialize doesn’t have a good antonym. Is it Unserialize? Is it Deserialize? It does it matter… And yet it does.

As you can see, deserialize produced the best results. Unserialize pointed toward PHP unserialize and jQuery deserialize in stack overflow and Query Forms produced the worst however I included it in as a newer developer example. Hopefully, people look for deserialize quickly. That being said, people may end up looking for a non-plugin solution…

When a 10,000 developer’s recreate the wheel…

However, I think theres something to be said for this comment here. If theres something not available in jQuery, people will generally avoid plugins if they can. This can be associated to:

  • Plugin’s are not held to the jQuery code standard
  • Plugin’s may be poorly coded
  • Plugin’s may not offer everything the developer needs

In addition, some things are simple enough that there is no need to use a plugin for them. As a result, instead of people spending 5 hours to implement 5 features, they spending 5 hours perfecting loops and queries. And even after that 5 hours, it may not be perfect. What’s more is, writing this may take a day or may take a week. As a result we lose out on valuable time for developers to solve real world problems, instead they are solving development problems. We can also look at this time wasted at scale.

  • If 1000 people rewrite “deserialize” or “serialize to Object”
  • if on average it takes a person 4 hours
  • 1000*4 = 4000 hours lost from our precious developers lives.
Is Change Necessary?

I think there is food for thought: Are form’s common to interact with or are they just better off ignoring? Do you build only the simplest tools or do you build a full fledged form handler? Why should the jQuery team Care? Supply and Demand.

What are jQueries Competitors?
  • Zepto – equalivalent form support
  • Cash – less form support
  • Minified – No form support
  • Snack – No form support
  • $dom – No form support
  • xui – No documentation, I’m not about to start looking at their code. Ain’t nobody got time for that.
  • dojo – Their documentation is hell.
  • ExtJS – Their documentation isn’t much better
  • Mootools – no form support
  • YUI – this has no form support
  • Medley – I’m not suprised
  • Perhaps you don’t need it – Don’t get crazy, I don’t feel like looking at crazy looking code.

So it would seem much more of development for developers comes from either providing a wrapper for everysingle function, following jQueries lead or making it smaller. Ok, so using different tools would be too frustrating or not provide us what we need.

Are there enough vocal demanders?

I find programmer school’s of thought interesting

  • The cool request – People requesting something because it would be a cool feature but do little to no work.
  • Not Made Here – People that write stuff just because they want to make everything in house
  • Part of the team – Once you get on a successful team, it means funding. It means everyone carries their weight. It also means a hive mind mentality where your voice will generally try to agree with others. And theres no reason to fight with other successful teams.
  • Too Bad of a programmer to have a say – Everyone else is so advanced, why should I say anything?
  • Think they are god’s gift to the earth – Think their opinion hold’s the most weight.
  • Something Else – Which you may fit in to.

2.5/5 of these people will likely not make requests. Teams will ask other teams for requests, as a result those features may be implemented because a successful team holds more weight than a single person.

However, if you think that these features should be implemented, say something. But generally death by a thousand cuts is a bad plan as it causes disorganization. If you think it should be included, search for the issue and post there. Heres a link to what I found.

MVC as applied to wordpess and a moment of silence for XSL

So, finishing up the backbones of the Clockin Plugin, I’ve found the next steps are to see it as I had it on my old site. With a multitude of charts and such. However, the display for the clockin plugin isn’t static. In fact its quite dynamic. The entire idea of a “clock in” is its date as such it will be changing almost daily. This is ok and unfortunate for me in that it was what bogged down my load times before. I gotta do what I got to do.

Now there are a few things I’m going to be doing

  1. Add a specific ui thats just for clock_in_project
  2. Add a specific ui thats just for users, and allow them to be searchable
  3. Start Moving away from the 2014 base (while attempting to keep a lot of the great parts)
  4. Create my old charts
  5. Cache days that are not current days for easy access

But my to do this isn’t why I’m writing this blog post, the reason I’m writing this is to explain what a model view controller is and what wordpress offers.

The best way I can explain the model view controller is this:

  • Model is an object in your database
  • View is how you’ll be viewing the Model
  • Controller is directing what Model to choose and what view to choose for it
    -This can be based off: User Request, Admin Request, App Request and Default

With wordpress, our MVC is simple: we have post types, we have a theme, we have a url.
Whenever a user makes a request at the top thereurl, what we’re actually doing is making a request.
Now from my experience there are two main forms of requests, archive, singles. Archives will show you a list of items based off a query. Singles may also be based off a query, the difference is that you get full frontal information instead of a bunch of items.

Why does this matter?

Well for the clock in post type, we’re going to have to do some very special things. And Unfortunately as is the default it renders as if its just a regular post. We’re going to change that.

Its something very simple, where we can base it off of file structure. But I’d prefer not

switch (get_post_type( get_the_ID() )){
case "type_a": break;
case "type_b": break;
default: echo "ah, the good old default";
}

As simple as this we can go through and pick our view. we can also mix and match and a bunch of funky things.

One thing I want to point out is a sad sad truth about MVC, XSLT. XSLT was designed to make HTML the view component of choice. Where we would take in our model, see what we had and apply the appropriate templates. Important to note, it was all (well kinda) XML. It gave people the conceptual graduation platform to move up to. So why didn’t it work out?

XSLT has a major flaw, most Databases don’t return XML. If your database isn’t returning XML, your going to have to Transform it into XML. If you’re transforming, your wasting time. Especially when you can just use the raw data retrieved to fill in the dots. Another Major flow is that despite how awesome Xpath is, there isn’t a direct correlation from url concepts o XPath concepts.

What people need to understand is the url is the command, just as XPath is a command. And most people go from HTML, CSS, File system into PHP and Javascript where either they sink or swim. XSL and Xpath had the opportunity to make that bridge easier. But they died as other CMS’s popped up and took over. Will we see them again? One day maybe, I certainly try to use it when i can. But I highly highly doubt it

ClockIn: Preparing the Shortcode

Last time I basically shutdown all possibilities of using google calander, but thats fine, SQL is an efficient alternative and it should be no issue.

CREATE TABLE Clock_ins (
 time datetime DEFAULT NOW() NOT NULL,
 duration int DEFAULT 0 NOT NULL,
 user tinytext NOT NULL,
 project tinytext NOT NULL
 );

Now, theres 3 main UIs I need to focus on

  1. Clock In, Clock out-This will be in the sidebar, or really where ever someone wants to put it
  2. Project Chooser-When we begin to clock in, we need to be able to choose from our existing repositories
  3. Clock In Viewer (User and Project mode)-Whats a database if we can’t view it? Here we give sexy charts for people to look at to make them feel comfortable (We’ll worry about this later

So For Clock In, Clock out…. We’re going to want to add in a some WordPress Shortcode tags so that we can place it anywhere we want Our shortcode is going to be called [clock_in] and theres three major things we’ll be needing from the user -Their user id -their github id -The project they’re going to clockin to

function clock_in_setup( $atts, $content=null) {
 $current_user = wp_get_current_user();
 $message;
 $href;
 $type = "ajax";

 if ( !($current_user instanceof WP_User) ){
 $message = "Please Login First";
 $href = wp_login_url( get_permalink() );
 $type="self";
 }else if(($meta = get_user_meta($current_user->ID, "clockin")) == array()){
 $json = json_decode(file_get_contents(plugin_dir_path( __FILE__ )."/secret.json"));
 $cid = $json->cid;
 $redirect_uri = plugins_url("auth.php", __FILE__);
 $state = "clock-in_plugin".$current_user->ID;

 $href = "https://github.com/login/oauth/authorize";
 $href .= "?client_id=".$cid;
 $href .= "&redirect_uri=".$redirect_uri;
 $href .= "&state=".$state;

 $message = "Authorize our plugin";
 $type="blank";
 }else if(isset($atts["cur_project"])){
 $nonce = wp_create_nonce("clock_in");
 $href = admin_url('admin-ajax.php?action=clock_in&proj='.$atts["curproject"].'&nonce='.$nonce);
 $message = "Clock in!";
 }else if($meta["clocked"] == true){
 $nonce = wp_create_nonce("clock_in");
 $href = admin_url('admin-ajax.php?action=clock_out&nonce='.$nonce);
 $message = "Clock out!";
 }else{
 $href = plugins_url("clocked.php", __FILE__)."?action=in";
 $nonce = wp_create_nonce("clock_in");
ob_start();
?>
 Choose a project to Clock Into
 <div class="clockin-wrap">
 <a style="display:inline-block;height:144px;width:64px;background-color:#000;"></a>
 <div class="clockin_projects" style="display:inline-block;height:144px;width:144px;">
 </div>
 <a style="display:inline-block;height:144px;width:64px;background-color:#000;">
 </a>
 </div>
<?php
 wp_enqueue_script ('clock_in_proj');
 wp_localize_script('clock_in_proj', 'clock_in_vars', array("github_user"=>$meta["github"], "clockin_uri"=>admin_url('admin-ajax.php?action=clock_in&&nonce='.$nonce)));
 return ob_get_clean();
 }
 ob_start();
 ?>
 <div class="clockin-wrap">
 <a class="clockin_anchor" href=<?php echo $href; echo ($type != "ajax")?" target=".$type.'"':''; ?> ><?php echo $message ?></a>
 </div>
 <?php 
 if($type == "ajax"){
 wp_enqueue_script ('clock_in');
 }
 return ob_get_clean();
}

What I’m doing here essentially is creating a link where ever the shortcode is. The Link will either;  direct to login, direct to github authorization, if its a project page, allow person to clock in, display logged persons projects to clock in or show clockout link. Next we need to make sure we authenticate with github, then display our projects properly