Archive for August, 2011

Proxying around remote JSON HTTP GET with Sinatra

No Comments »

If you have a remote host that has some JSON data you need you can very quickly and easily proxy that host's response using Sinatra. This is useful for local development. There are other ways to do this of course, but in a pinch the following solution works, albeit without error handling.

#./server.rb
require 'net/http'

HOST = 'example.com'

get "/package/details.json/:id" do
  content_type "application/json"
  uri = URI::HTTP.build(
        :host  => HOST,
        :path  => "/package/details.json/#{params[:id]}",
        :query => 'some_parameter=abc'
  )
  Net::HTTP.get(uri)
end

get "/simulate/details.json/:device_identifier" do
  content_type "application/json"
  uri = URI::HTTP.build(
    :host => HOST,
    :path => "/simulate/details.json/#{params[:device_identifier]}"
  )
  Net::HTTP.get(uri)
end

backbone.js: Collections of Models within Models

No Comments »

This isn't your typical backbone.js scenario but its fortunately easy to solve, and special thanks to Joey Beninghove for shaving several hours of hard work off my plate by helping me arrive at a solution.

My problem domain is this: we (by we I mean an intern at my company) are building a tool that displays this structure called a package. The package looks something like this...

 package
|- nodes [0..n]
    |- node
        |- assets [0-n]
        |   |- asset
        |- actions [0-n]
            |- action

Essentially a tree of collections. Behind the scenes all of these models (package, node, asset, action) are full blown models. In this particular case though we wanted to display the structure of a package which means we get the entire package's JSON all at once, like a giant turd (snippet):

{
  "CreateTime" : "/Date(1283319058700)/",
  "Id" : 10000,
  "ModifyTime" : "/Date(1283319060013)/",
  "Name" : "Some Package Name",
  "Nodes" : [ { "Actions" : [ { "FromNodeId" : 53730,
              "Name" : "Dismiss",
              "ToNodeId" : 0
            },
            { "FromNodeId" : 53730,
              "Name" : "View",
              "ToNodeId" : 53731
            }
          ],
        "Assets" : [ { "AssetBinaryId" : null,
              "AssetClass" : { "Id" : 8,
                  "Name" : "ImageURL"
                },
              "AssetFormat" : { "Id" : 1,
                  "Name" : "PNG"
                },

              "Data" : "/SomeUrlHere?querystring",
              "Id" : 52616,
              "Name" : "Banner Image",
              "NodeId" : 53730,
            } ],
        "Name" : "Banner",
        "NodeClass" : { "Id" : 1,
            "Name" : "Banner"
          }
      },
⋮
}

As I was working the solution at the time in a regular HTML file I was relying on console.log and Safari's excellent developer tools. (Note: to retrieve JSON data from a local file in Chrome you have to launch Chrome with a command line argument.) The solution looks something like this (without worrying about the Router or Views):


<html>
⋮
  <head>
    <script type="text/javascript" src="js/vendor/backbone/underscore.js"></script>
    <script type="text/javascript" src="js/vendor/jquery/jquery-1.6.2.js"></script>
    <script type="text/javascript" src="js/vendor/backbone/backbone.js"></script>
  </head>
  <body>
    <script type="text/javascript">
window.Action = Backbone.Model.extend({
  initialize : function() {
    this.fromNodeId = this.get('FromNodeId');
    this.toNodeId = this.get('ToNodeId');
    this.name = this.get('Name');
  },
  nextNode : function(nodes) {
    return nodes.detect(function(node) { return node.id == this.toNodeId}, this);
  },
  previousNode : function(nodes) {
    return nodes.detect(function(node) { return node.id == this.fromNodeId}, this);
  }
});
window.Actions = Backbone.Collection.extend({ model: Action });
window.Asset = Backbone.Model.extend({
  initialize : function() {
    this.assetBinaryId = this.get('AssetBinaryId');
    this.data = this.get('Data');
    this.id = this.get('Id');
    this.name = this.get('Name');
  }
});
window.Assets = Backbone.Collection.extend({ model: Asset });
window.Node = Backbone.Model.extend({
  initialize: function() {
    this.assets = new Assets(this.get('Assets'));
    this.actions = new Actions(this.get('Actions'));
  },
});
window.Nodes = Backbone.Collection.extend({ model: Node });
window.Package = Backbone.Model.extend({
  initialize : function() {
    // the following line forces 'this' to refer to the Package instance in the
    // function `fetch_success`
    _.bindAll(this, 'fetch_success');
    this.bind('change', this.fetch_success);
  },
  // specifying the URL as a function gives us a bit more flexibility
  url : function() {
    return "data/package/" + this.id + ".json"
  },
  // invoked automatically when the change event is invoked which happens when fetch is successful
  fetch_success : function() {
     this.nodes = new Nodes(this.get('Nodes'));
     this.createTime = this.get('CreateTime');
     this.modifyTime = this.get('ModifyTime');
     this.name = this.get('Name');
  }
});

<!-- and... -->
$(document).ready(function() {
  pkg = new Package({id:"10000"});
  pkg.fetch({ failure: function(model, response) {
    console.error("ERROR");
    console.log(response);
  }});
    window.pkg = pkg;
    console.log(pkg);
  </script>
  ⋮
  </body>
</html>

Painfully Hellish Plaintext and WordPress

No Comments »

I'm working on a Wordpress site for a general contractor friend of mine and we wanted to make something really easy for him to use to show before/after pictures. Now after a bout of hacking on Wordpress - be it plugins, theme changes, or just reading the API documents - I typically have to delude myself into believing that Wordpress was written in some sensible language, like Perl, so I can sleep that night. Tonight the healing process will have to begin a bit later than usual.

I settled on a Before/After plugin but not one of the jQuery slider-type plugins. The jQuery-based ones use a slider to show two pictures that pretty much have to be taken from the same angle/same scene/etc. to get a really good effect. Our needs were for a before/after in a room to display tile work or anything else that might come up. This plugin got me about 90% of the way. Its one of those plugins where it has pretty good admin integration - not the greatest, except when you post its dead simple (drag two images from your media gallery into a Before/After columns) - but fails on executing the full deal. The author suggests you edit your theme's template files to add some PHP to see if the current post has a before/after gallery associated with it and then make the call for the appropriate image. You'd likely have to do this in your single post and index templates. This just felt dirty to me.

The plugin is contained a single file beforeafter.php which makes our job all the easier.

Around line 30, prior to the declaration of $beforeafter we add an action:

#./wp-content/plugins/beforeafter/beforeafter.php
⋮
add_action('the_content', 'before_after_content_action', 5, 1);
⋮

So what's that 5 and 1 in there for? Glad you asked. So the five is somewhat sensible, its the priority in which your action will be executed when considered against the other actions registered for the "the_content" action. The 1? Well that is the number of arguments your function accepts. Uh, come again? Yeah. Exactly. You'll note that we cannot just pass arguments to this function, Wordpress will take care of that for us. And how do we know what arguments we're going to get? I wasn't able to find a definitive list and a lot of answers out there suggest just reading the Wordpress source code, so I guessed, and I guessed right.

After the $beforeafter I added our action:

#./wp-content/plugins/beforeafter/beforeafter.php
⋮
function before_after_content_action($content) {
        global $beforeafter;
        global $post;

        if (!($beforeafter->is_gallery($post->ID)))
                return $content;

?>
<table class="center" width="100%">
        <tr>
                <td class="center">
                        <?php $beforeafter->gallery('before', $post->ID, 'thumb', true, false, 'shadowbox'); ?>
                        <br />Before
                </td>
                <td>
                        <?php $beforeafter->gallery('after', $post->ID, 'thumb', true, false, 'shadowbox'); ?>
                        <br />After
                </td>
        </tr>
</table>
<?php
        return $content;
}
⋮

Those global declarations cause me to dry heave.

So it turns out that your action method should accept one parameter $content and return that value almost like a filter. The good news is that in an action method you can just, you know, throw up all over inside your editor with <?php ?> interspersed with code and that stuff will be output during execution as you would expect.

(That final argument, the 'shadowbox', lets you integrate the Wordpress 'shadowbox' incredibly easily. I was impressed.)

If I can manage it I'll try to put a better admin UI on this stuff and get the plugin out on Github and register it with Wordpress so the manual editing nonsense isn't necessary. I know there has to be at least another person out there who wants easy before/after functionality in their blog.

And the good news: I learned a lot about using vim during this process.