Category Archives: Uncategorized

IE6 is dead, maybe we can move on

Now that IE6, 7 & 8 have been sent to the heavenly software repository(1) it’s maybe time to stop relying on jQuery quite so much and have a look at some of the ‘new’ things which javascript ES5 can do natively. We’ve been clinging on to things like $.each and $.isArray when javascript and most browsers can do it natively using Array.forEach and Array.isArray.
If you really, really, really have to support these old browsers then maybe you can just use the polyfills in the mozilla reference, at least then you can definitely move on and use Javascript as it should be.
As the ES5 reference shows there is widespread support for most of the features, unfortunately the same cannot be said for ES6 yet.

(1) Rumours of their complete death may be exaggerated but the downward trend gives us hope for the future.

Rubygems, bundler and ssl error

I experienced a ‘Could not verify the SSL certificate for https://rubygems.org/’ error when doing a bundle install on OSX with RVM recently. A bit of googling revealed that there was a good chance that the CA certificates that curl uses were out of date

Solution:
Update rubygems gem update --system
Update RVM rvm get head
List certificate status rvm osx-ssl-certs status all
Update certificates rvm osx-ssl-certs update all

RVM was 1.18.15 before the update and 1.21.7 after the update.

Ember JS: MVC in the browser. Part 3 – Nested Resources

In part 2 we created templates so that we could view any of our blog posts along with the models and controller actions to support this. We also used ember-data to create a store which uses a FixtureAdapter along with some hardcoded Post fixtures to load our models. A Post with a title is not much use on its own, we also want people to be able to add comments. We will have to extend the post route to add a nested resource. We will also need a new model to represent the nested resource. The code for this part is available here. Open app.js in an editor and change the post route to match the following:

this.resource('post', { path: '/posts/:post_id' }, function() {
  this.resource('comments');
});

This means we will now have a /posts/:post_id/comments route.

Open the index.html page in a browser and examine the routes in the console. Remember our old friend Router.router.recognizer.names? (btw. I noticed in Firefox you may need to use App.Router.router.recognizer.names). You will see that comments route has been added. Lets add a comments model and fixtures. Add the following to app.js

App.Comment = DS.Model.extend({
  post: DS.belongsTo('App.Post'),
  text: DS.attr('string')
});

and add the following within the App.Post model making sure that you have a comma between any lines

comments: DS.hasMany('App.Comment')

Each Post can now have many Comment(s). Add some comment fixtures to app.js:

App.Comment.FIXTURES = [{id:"1", text: "First Comment"}, {id:"2", text: "Second Comment"}, {id:"3", text: "Third Comment"}, {id:"4", text: "Fourth Comment"}, {id:"5", text: "Fifth Comment"}, {id:"6", text: "Sixth Comment"}, {id:"7", text: "Seventh Comment"}, {id:"8", text: "Eighth Comment"}, {id:"9", text: "Ninth Comment"}];

We also need to change the Post fixtures to tell them that they have some comments:

App.Post.FIXTURES=[{ id: "1", title: "First Post", comments: [1, 2, 3] }, { id: "2", title: "Second Post", comments: [4, 5, 6] }, { id: "3", title: "Third Post", comments: [7, 8, 9] }];

Note that we have added a ‘comments’ attribute in each Post fixture with an array of the Comments they have. [1, 2, 3] means that this Post has the Comments with ids 1, 2 & 3. Go to /posts/1/comments/1 to check that they render correctly.

Change the post/index template to the following so that we can see the comments:

<script type="text/x-handlebars" data-template-name="post/index">
  {{title}}
  <ul>
    {{#each comment in comments}}
      <li>{{comment.text}}</li>
    {{/each}}
  </ul>
</script>

Go to /posts/1 and you should see the text for each Comment appearing under the Post title.

We can now add a link to each comment but before this we need to tell the router how to route to them. We want the route to look like /posts/:post_id/comments/:comment_id
To achieve this we need to add the following to the posts resource router definition

this.route('comment', { path: 'comments/:comment_id'});

We will also need a post.comment template in index.html

<script type="text/x-handlebars" data-template-name="post/comment">
  {{text}}
</script>

What if we wanted to add a new comment to a post? We will add a posts/:post_id/comments/new route and templates. Change the comments resource under the post resource in the router to

this.resource('comments', function() {
  this.route('new');
});

Then add a comments outlet template and a ‘new’ one

<script type="text/x-handlebars" data-template-name="comments">
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="comments/new">
  Comments New
</script>

 

If you refresh and look at the available routes we now have comments.new. Go to /posts/1 and click on the New Comment link and you should see the “Comments New” text. Not much use though, we need a text box for the comment and a button to submit. Add the following to the comments/new handlebars template

<form {{action save on='submit'}}>
  {{view Ember.TextArea valueBinding="text" placeholder="Enter comment here"}}
  <button type="submit">Create Comment</button>
</form>

Here we tell the template that when the forms “Create Comment” button is clicked, ie on submit, it should call the “save” action in the CommentsNewController. We need to create that controller. In the TextArea we have bound the “text” value to the controller. Add the following to app.js

App.CommentsNewController=Ember.ObjectController.extend({
  needs: 'post',
  text: null,
  save: function() {
    var post = this.get('controllers.post.content');
    App.Comment.createRecord({ post: post, text: this.get('text') });
    this.get('target').transitionTo('post.index');
  }
});

Firstly we tell this controller that it needs to know about the PostController so that it can tell what post the comment is for. We do this through needs: 'post'. The text: null bit is the value we have bound to the TextArea in the template. The save function is what happens when we click the button. Firstly it finds the post through controllers.post.content (facilitated via the ‘needs’ syntax), the we create a new Comment with the text value. Finally we transition back to the post. this.get('target') gives us an instance of the router. Try adding a new comment and see what happens. Note that since we are using the FixturesAdapter the ids may look a little bit odd.

One final thing we should do is reset the comments TextArea box in the comments/new template when we transition to the route. If we don’t then it will contain the last thing we entered in to it. Add this to app.js

App.CommentsNewRoute=Ember.Route.extend({
  setupController: function(controller, model) {
    controller.set('text', null);
  }
});

setupController is a hook that all routes have and allows you to set the model or modify the controller.

To recap, we created a comments nested resource for post and added the route ‘new’ to it. We added a Comment model and fixtures and linked them to the Post model via hasMany and belongsTo. We added the comments to the post.index template and added a route with a path for each post.comment so we could link to them. We created the comments.new template with a form that we could submit and the CommentsNewController with a save action to create the new comment.

Ember JS: MVC in the browser. Part 2 – Templates

In part one we added some routes defining our posts resource and for an individual post. We also learned how to inspect our Router object to see what we had defined using App.Router.router.recognizer.names in the web console. Now to create some templates to display when we transition through our routes. Download the code here. In part one we defined an application template with a handlebars {{outlet}}. We will add templates to render in this outlet.

Go back to index.html and add the following:

<script type="text/x-handlebars" data-template-name="index">
  {{#linkTo 'posts'}}Posts{{/linkTo}}
</script>

<script type="text/x-handlebars" data-template-name="posts">
  Posts
</script>

Refresh the page and you should see a link to ‘Posts’ under the title, clicking on it will take you to a page with the title and the word ‘Posts’. Looking at the console you can see that we transitioned from index to posts. Both of these templates were rendered in the main application template in the {{outlet}} block. Next we can add a link to individual Posts inside the Posts template and create a template for these individual Posts.

Change the ‘posts’ template to the following

<script type="text/x-handlebars" data-template-name="posts">
  <ul>
    {{#each model}}
      <li>{{#linkTo post this}}{{title}}{{/linkTo}}</li>
    {{/each}}
  </ul>
</script>

However, if you refresh the ‘/posts’ page you will no longer see anything. That is because we have no models and we definitely have no data. To remedy this we will add some. We start by creating a store. Go to app.js and add the following

App.Store = DS.Store.extend({
  revision: 12,
  adapter: 'DS.FixtureAdapter'
});

If you refresh the page you will probably see an error along the lines of ‘Undefined variable: DS’. This is because we need to add the ember-data library. To get it you can either clone the ember-data repository and run rake dist (https://github.com/emberjs/data#getting-ember-data) or download the latest build from http://builds.emberjs.com). In the future ember-data may be bundled along with ember but until then this is the way to get it.

So, download ember-data, add a <script> tag to index.html to load it, placing it after ember but before app.js, and refresh again. Now, the revision: 12 part is to check that it is compatible with the emberjs you are using, if not it will be reported in the console. The adapter part is optional but we are telling it to load data from fixtures that we will specify in javascript. Reload and all should be ok. We will now define a post model and some fixtures. Add the following to app.js

App.Post=DS.Model.extend({
  title: DS.attr('string')
});

App.Post.FIXTURES=[{ id: "1", title: "First Post" }, { id: "2", title: "Second Post" }, { id: "3", title: "Third Post" }];

Refresh the page and…..nothing. We have to tell ember what to do when it gets to the posts route. Add the following to app.js, after the main routes definition.

App.PostsRoute=Ember.Route.extend({
  model: function(){
    return App.Post.find();
  }
});

Here we tell ember that when we transition to ‘posts’ we need to find all the Post models that exist, in this case we return all the fixtures we have created. Refresh and all the posts should be shown using the title as a link. If you look at the definition for the posts template we created earlier you can see that we iterate over each of the models that the PostsRoute returns and add a link for each with the title as the text. {{title}} is a handlebars helper which tells it to get the attribute title from the current model in scope. Refresh the page and you should see links to 3 posts, hover over them to see the urls they link to. They should be linking to /posts/1 etc. Click on one of the links and you will see that we transition into post.index but there is nothing shown. Surprise, surprise we need a to define a template. Add the following to index.html after the currently defined templates:

<script type="text/x-handlebars" data-template-name="post/index">
  {{title}}
</script>

Refresh the page and you will see this warning in the console:

WARNING: the immediate parent route ('a') did not render into the main outlet and the default 'into' option ('p') may not be expected

Rember earlier we defined the {{outlet}} in the application template, ember expects every parent template to have an {{outlet}} into which it can render its children. In this case it is saying that it wants to render post.index into post but it can’t find it. We need to define a post template with the following in index.html

<script type="text/x-handlebars" data-template-name="post">
  Post
  {{outlet}}
</script>

Don’t forget to add the ‘Post’ text in the template, you will see why in a second. Refresh and you will see the ‘Post’ text but no title for the post. Well, it turns out there is a ‘feature’ (polite term for a bug) which means that in the current version the ‘default’ behaviour for a parameterised route does not work out of the box. Ember should know that because we defined the route with /posts/:post_id that it should return the model with id equal to :post_id when we transition to post.index with posts/1 etc but for the moment we have to tell it. We need to define a PostIndexController to get things back on track. Add the following code to app.js so we can see what is happening:

App.PostIndexRoute=Ember.Route.extend({
  model: function(params) {
    return App.Post.find(params.post_id);
  }
});

Refresh and….still nothing. Ok, I knew that was going to happen, unfortunately the bug means that empty params are passed to a nested route. Use your debugger and examine the params object yourself. All is not lost however, change the model hook to

model:function(params) {
  return this.modelFor('post');
}

Refresh. Yes, you should now see the text ‘Post First Post’. You can remove the unneeded ‘Post’ text from the post template and refresh again. Try going to posts/2 and posts/3 to convince yourself that it is all working.

So to recap. We have created an ember application which logs transitions between routes. It has 3 routes: index, posts and post.index. We have 5 templates: the main application one with {{outlet}}. The index template ie ‘/’. The posts template. A post template with an outlet for its nested routes and a post.index template to ‘show’ each post. In part 3 we will look at nested routes.

Data consistency is everything

I have recently been working with some social scientists on estimating the prevalence of certain disabilities in the UK regions using census, health survey for england and R. One of the aims is to show the stats on a map. Edina’s thematic mapping service helps here. However I was having difficulty with inconsistencies in the UK district classifications. Why is the source data for each of the countries in the UK (available through edina again) published in a slightly different format:

Scotland:

“COUNCIL_AREA”,”NAME”,”ONS_CODE”

“01”,”Aberdeen City”,”QA”

England/Wales:

COUNTY_CODE_2001 DISTRICT_CODE_2001 DISTRICT_NAME_2001

00 AA City of London

Northern Ireland:

District,District Labels

95AA,Antrim

So, we have two in csv, one in tab, one which uses quotes around fields and headers, one which joins the codes into a 4 letter string and different orders in each file. How much time could we all save if the creators of such data talked to one another.

Ruby on Rails and IIS on Windows 7

Here are the steps I needed to install ruby 1.8, rails 2.3, sqlserver to run our https://github.com/myGrid/methodbox codebase on a Windows 7 platform and run it all under IIS. It should also work for any rails 2 or 3 project.  If you use rmagick or libxml-ruby then pay attention to the installing gems part for some dlls you need to install along with where to get them.

So, having tried various solutions involving fastcgi and url rewrite which I could not get to work on IIS 7.5 under Windows 7 I found http://www.helicontech.com/zoo . I’ve seen the people behind it on various other posts on msdn etc so there is some history of them working on IIS, fastcgi and url rewrite. In fact I think they have had a url rewrite product available for a number of years.

* Install Rails

1) Install the Web Platform Installer from http://www.microsoft.com/web/downloads/platform.aspx
2) Add http://www.helicontech.com/zoo/feed as a new feed
3) From the zoo tab select Blank Ruby on Rails Rails project and Ruby1.8 and click the install button. It will also install other dependencies.
4) When installing the blank project it will pop up and ask you where to put it along with other required details like the name. Make a note of where the project lives since we need a couple of files from it.
5) From the blank rails project we need the web.config files in the projects root and public directories.  Place these in the same place in your rails project directories.  To use Ruby1.9 we need to replace ruby.1.9.pipe in the web.config in the projects root directory with ruby.1.8.pipe. You may also have to add the path to ruby’s bin directory to your environment variables – C:\Ruby18\bin or C:\Ruby19\bin
6) Ensure that the projects directories are writeable by the IIS_IUSRS user.
7) Add the project to IIS with the project path pointing to the rails projects root directory (not public like you would with a rails project under apache).

* Install Git

This is used for version control and can be found on http://git-scm.com/ Install the version marked ‘Full installer for official Git for Windows 1.7.8′ or similar (version name might be different).

* Install required gems (libxml and imagemagick specific instructions)

There are various 3rd party dependencies that the gems that MethodBox requires including imagemagick (ie. rmagick) and libxml-ruby. On windows this requires a little bit of user intervention during the install process. Go to http://www.imagemagick.org/script/binary-releases.php?ImageMagick=uteqfietdab37ghqrvfuvoul55#windows and download http://www.imagemagick.org/download/binaries/ImageMagick-6.7.3-7-Q16-windows-dll.exe
Double click and go through the installer, selecting to install C and C++ header files and libraries from the additional options page
add environment variable CPATH=\path\to\imagemagick\include and LIBRARY_PATH=\path\to\imagemagick\lib

There is a high chance that the libxml-2.2.dll needed for libxml-ruby is not present in the lib folder and will pop up an error.  The dll can be found in C:\Ruby18\lib\ruby\gems\1.8\gems\libxml-ruby-2.2.0-x86-mingw32\lib\libs\  Copy the libxml, iconv and zlib dlls and put in the C:\Ruby18\bin folder.

Note: If you are not using mysql then comment any mysql gem out of the Gemfile. Otherwise the system may complain about libmysql.dll missing.  If you are using mysql you need to copy the dll from the mysql/bin folder to the ruby lib folder.

* SQL server and rails

1) Find out your SQL server details. If your SQL server instance has not been allowed through the firewall then you need to find out its details: open up the sqlserver management console (which you can install along with sqlserver express via the Web Platform Installer – I recommend this way, downloading on its own and installing does not work correctly) and look at your db details.
2) Set up a Data Source Name (DSN) for your ODBC connection.  This is not that well documented so you need to find the C:\Windows\sysWOW64 directory and start the odbcad32 programme.  Then you add a system DSN for your instance of sqlserver.
3) Set up your rails projects database.yml as normal with the following records:

adapter: sqlserver
mode: odbc
dsn: sqlserverapp-dsn (the one you created earlier)
username: user
password: secret
host: localhost (or whatever)

Ruby, Windows and RMagick

Been doing a lot of rails work on windows recently and ran into some issues that needed solved.  Just like on Unix, to get the RMagick gem working on a windows platform you need to install ImageMagick.  Go to http://www.imagemagick.org/script/binary-releases.php?ImageMagick=uteqfietdab37ghqrvfuvoul55#windows and download http://www.imagemagick.org/download/binaries/ImageMagick-6.7.3-7-Q16-windows-dll.exe

Double click and go through the installer, selecting to install C and C++ header files and libraries from the additional options page (this is very important)

Then add environmant variable CPATH=\path\to\imagemagick\include and LIBRARY_PATH=\path\to\imagemagick\lib

You can then ‘gem install rmagick’ and it will build it using the native image magick libraries.

Bundler, OSX and the MysqlCompat::MysqlRes error

If you get the uninitialized constant MysqlCompat::MysqlRes error when trying to run your Rails app all the evidence points to it being a 32 v 64 bit issue.  However, I had built mysql for the x86_64 architecture and the mysql gem installed was also for 64 bits.  So why was I still getting this error.  It turns out that bundler was building the mysql gem in 32 bits.  OSX Snow Leopard ships with Ruby in a universal binary containing the ppc, i386 and x86_64 binaries and for whatever reason bundle install was using the 32 bit ruby and re-building everything even though I had the gems already installed in the system in 64 bit mode.  This could be because the user doing the building was 1) unprivileged and 2) using bundle install \--path=vendor.  Maybe bundler was picking the first version of ruby that was appropriate to the platform.  However, doing bundle install \--deployment also had the same issues. I have no idea why it was rebuilding gems that already existed on my system. The way to get round it was to force bundler to build in 64 bits by using env ARCHFLAGS='-arch x86_64' bundle install --path=vendor
Maybe the best idea is not to use the Ruby that ships with OSX and build one appropriate to your environment in the first place.

Tab navigation and tooltips

We use the tabifier javascript from barelyFitz in a few places in MethodBox.  However, I wanted it to have a different, more descriptive tooltip than the tab title.  The default code doesn’t seem to do this so I added a couple of little changes to make this happen.

You can see the complete file here but below is a quick synopsis of the changes:

added a boolean to keep track of whether you want a different tooltip than the tab title:

this.differentTooltip = true;

if this isn’t the behaviour you wanted then that’s ok:

if (!this.differentTooltip) {
t.headingText = t.div.title;
}

however, if the tooltip is to be different then make sure the
link for the tab is correct:

if (this.differentTooltip) {
DOM_a.title = t.tooltipText;
} else {
DOM_a.title = t.headingText;
}