BlogFeed-icon-28x28

About_josh_adams

February 1st, 2013 08:54

So a recent article that Seth sent to me had a great quote from Alan Perlis in it:

A language that doesn't change the way you think about programming is not worth learning. - Alan Perlis

This is one of the reasons that I loved Ruby so much when I first came to it. I was developing .net code, and I looked at programming as just a way to get some projects done for the company I worked for. I didn't expect it to be fun or engaging. I was good at what I did, and I took a little pride in that, but mostly I was just doing a job.

Then I came in touch with the Ruby community, and there was all this lore. There was MINSWAN, and there was YAGNI, and there was DRY, and there was a widespread belief that you would get better at programming by sharing code.

Then when the language itself came into play, there were iterators and blocks and functions-as-first-level-objects, and it all was so new and exciting to much-younger me.

The Ruby language changed the way I thought about programming, with its sugar-heavy syntax and its lisp/smalltalk roots. The Ruby community changed the way I thought about programming, in that there seemed to be such a widespread focus on programming as a thing that could bring you joy, in-and-of-itself. Consequently, I feel that Ruby is worth learning twice by Alan Perlis' metric :)

About_josh_adams

February 1st, 2013 08:22

  • Implementing Persistence - Further discussion of the raidit learning-project
  • Resources to help guide architectural decisions when using Rails - Grant Ammons talks about things you can do to have a more granular design in your rails apps.
  • GTK3 Bindings Now Available in Ruby - thanks to David Chapman for the tip
  • BPython seems pretty fantastic - Also, the whole python objects-with-attached-documentation concept is just such a good idea. Wish Ruby had that.
  • Noel Rappin: Let's Make Testing Fun Again is one of the best videos on programming I've seen in the past year. Highly, highly recommended. I listened to it while driving, so if you don't have time to watch a video you can always do that and get great benefit.
  • Push-Button Deployments with Arduino - we obviously have to do this.
  • RbNaCl is a thing now. NaCl is a crypto library that focuses on smart defaults, because everyone that rolls their own with OpenSSL primitives and the like leave themselves open to attacks because they don't really understand crypto (like me). NaCl makes getting it right easy, and RbNaCl makes using NaCl from Ruby possible. Also, it's from Tony Arcieri, and he's always putting out great code.
  • Speaking of Tony Arcieri, I just started using his http gem in a project and it's pretty pleasant.
  • I've seen better_errors before but since I've been heavily involved in a javascript-only app I'd not spent the 2 minutes it took to actually try it out. Then last night I upgraded the version of draper we were using on a project by a major version, and used better_errors to figure out the API changes without reading too much documentation for draper
About_david_chapman

January 25th, 2013 11:07

Mutation testing is a way of evaluating your software tests. It does this by modifying your code in small ways. The idea is that a test suite that does not detect and reject the mutated code is considered defective. The main goal of mutation testing is to help locate weaknesses in your test suite or in sections of your application that are barely accessed (if accessed at all) during execution.

Mutant

If your project's code coverage is at 100%, that doesn't mean you've done a great job in testing your project. Mutant is a mutation testing tool for Ruby. It will systematically look for weaknesses by changing your source code and then expecting your test suite to fail due to this change in your source code.

Observe

lib/polygon.rb

class Side < Struct.new(:number, :length); end

class Polygon
  attr_reader :sides

  def initialize
    @pages = []
    @index = {}
  end

  def side(number)
    @index.fetch(number) {
      raise "Polygon doesn't have a side with number: #{number}"
    }
  end

  def add_side(side)
    @sides << side
    @index[side.number] = side
    self
  end
end

spec/lib/polygon_spec.rb

describe Polygon, '#add_side' do
  subject(:polygon) { Polygon.new }
  let(:side)        { Side.new(1) }

  it 'should return a polygon' do
    expect(polygon.add_side(side)).to be(polygon)
  end

  it 'should add a side to polygon' do
    polygon.add_side(side)
    expect(polygon.sides).to include(side)
  end
end

Now if we run mutant on this code we'll get something like this:

$ mutant -I lib -r polygon '::Polygon#add_side' --rspec-dm2

Mutant configuration:
Matcher:   #<Mutant::Matcher::Method::Instance identification="Polygon#add_side">
Filter:    Mutant::Mutation::Filter::ALL
Strategy:  #<Mutant::Strategy::Rspec::DM2>
Subject: Polygon#add_side:/home/david/dump/polygon/lib/polygon.rb:17

# ...

!!! Mutant alive: rspec:Polygon#add_side:/home/david/dump/polygon/lib/polygon.rb:17:3cc34 !!!
@@ -1,6 +0,5 @@
 def add_side(side)
   ((@sides) << (side))
-  @index[side.number] = side
   self
 end
Took: (0.05s)

subjects:   1
mutations:  8
noop_fails: 0
kills:      7
alive:      1
mtime:      0.04s
rtime:      0.18s

This fails because Mutant was able to completely remove @index[side.number] = side from lib/polygon.rb and our test suite didn't even care. This is the big advantage of Mutant. While tools like Simplecov will report that your project is 100% covered, it really isn't. Durring your tests, the line Mutant removed was executed, but no test was actually written to verify that a Side is getting stored in the index with its number. This will help you catch bugs in the future.

TL;DR

  • Mutation testing looks for weaknesses in your test suite by modifying your source code
  • Mutant is a Ruby tool for finding these weaknesses
  • 100% test coverage doesn't mean a strong test suite
About_josh_adams

January 25th, 2013 08:15

Links I've found enlightening this week await...

  • Squash is an open source bug tracking tool, akin to hoptoad, but it looks nicer and you host it yourself. I've not used it yet but it looks great.
  • Kelson is a fantastic-looking free font.
  • RubyJS is "A JavaScript standard library based on the Ruby core-lib"
  • CSS Selectors, Level 4 will, when they are widely distributed, solve some of the problems in raw CSS that we've been (till now) solving with tools like sass. "Parent selector" is the most exciting of those listed here, IMO.
  • Learning Ruby - if you want some ruby learning tools, this link's got you covered...
  • Dossier is a rails engine for generating reports from sql easily.
  • Building Rich Domain Models in Rails. Separating Persistence. This is a great blog post covering using a DataMapper pattern in Rails (without using DataMapper2, since it's noet yet production-ready)
  • The guy that wronte the above works for a company with a similarly-awesome blog: Nulogy Engineering. They cover nicely-separated Rails patterns as far as I can tell.
  • James Burke: Connections is an interesting look into the various connections between history and modern times across a variety of topics. Not related to programming, but very interesting nonetheless.

The Mechanics underlying the Specification

Automatic semicolon insertion (ASI for short) is with us in ES5 and it will continue accompanying us in ES6, so an understanding of how this mechanism operates is beneficial. This article maps out the operations our parsers are performing when we include and don't include semicolons. The rules for ASI are described in section 7.9 of the ES5.1 standard, and we will examine these rules laid out in this particular version since ES6 is still in draft phase.

The three basic rules for ASI are most accurately stated in section 7.9.1:

1. When, as the program is parsed from left to right, a token (called the offending token) is encountered that is not allowed by any production of the grammar, then a semicolon is automatically inserted before the offending token if one or more of the following conditions is true:

  • The offending token is separated from the previous token by at least one LineTerminator.

  • The offending token is }.

2. When, as the program is parsed from left to right, the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single complete ECMAScript Program, then a semicolon is automatically inserted at the end of the input stream.

3. When, as the program is parsed from left to right, a token is encountered that is allowed by some production of the grammar, but the production is a restricted production and the token would be the first token for a terminal or nonterminal immediately following the annotation “[no LineTerminator here]” within the restricted production (and therefore such a token is called a restricted token), and the restricted token is separated from the previous token by at least one LineTerminator, then a semicolon is automatically inserted before the restricted token.

Let's look at the steps an ES compliant parser might take when encountering the following code:

var one = 1
console.log(one)

Diagram showing parser path traversed

A given here is that the variable expression has already been parsed. The beginning of the console.log statement meets the first criteria in Rule 1 when the offending token, c, is encountered. As the parser follows the first rule of semicolon insertion and checks to see if the character is preceded by a new line break1, it discovers this is the case, and so it inserts a semicolon after the preceding token, which is 1, and continues forward. Now let's look at how simple it becomes when a semicolon is included:

var one = 1;
console.log(one);

Diagram showing parser path traversed

It just parses another token, the semicolon, which correctly closes the statement, as the parser intended, and carries onward. The following more complex example should help in furthering our understanding on the very different paths the parser may traverse:

return;
a + b;

Diagram showing parser path traversed

return
a + b

Diagram showing parser path traversed

Not only might an error in logic go unnoticed, but leaving out the semicolon clearly isn't the shortest path. At the minimum, the parser has to process three boolean statements and a function call for insertion of a semicolon, which itself is adding to the complexity. In the most extreme case (shown above), you are looking at three more boolean checks for a total of six moves and finally a semicolon insertion function call. Additionally, there's an overriding condition for all the rules:

...a semicolon is never inserted automatically if the semicolon would then be parsed as an empty statement or if that semicolon would become one of the two semicolons in the header of a for statement (see 12.6.3).

I hope this provides a solid reference on the underlying machinery behind ASI.


1 Named the line feed character in table 3 of chapter 7, section 3.

About_brandon_adams

January 23rd, 2013 14:46

I recently had the opportunity to work on a project that I decided to design in the browser and wanted to share what I believe are 3 steps that will help you get started with in-browser design.

  1. Know your stuff
  2. Right tool for the job
  3. Don't skimp on preparation

Know Your Stuff

Designing in the browser requires that you have a certainly level of proficiency with HTML, CSS, and JavaScript. In addition to those you will also need to have a working knowledge of whatever development tools and frameworks that will be used for the project as well. The level of proficiency and knowledge that you will need depends on many factors but for designers a couple will be how to reproduce visual effects and interactions outside of your favorite design tools. For example, CSS3 provides a great way to create gradients without using an image. However, if you're used to creating them in a design tool you'll have familiarize yourself with how to do them using one of several online gradient generators or doing them manually.

Right Tool for The Job

For many designers creating a complete design in a design tool has been the norm for a long time. This means not only visual assets such as icons, logos, and other imagergy but the entire design from top to bottom. When designing in the browser you have the opportunity to choose the right tool for the right job. With so many more devices and use cases to consider these days with mobile it really doesn't make as much sense to try and create multiple resolution dependent designs in a design only tool. That's not to say that there aren't some really good tools out there, and more are coming, that can be use to create great designs but that they may not be the right tool. Use those design tools for what they are best suited for and try doing other things such as your grid, layout, and typography in the browser.

Choosing the right tool for the job goes beyond design tools. Designing in the browser will challenge your way of thinking about certain aspects of a design. In your design you may have included the concept of an image slider but, now that you're in the browser which of the many sliders out there do you use? There are dozens of questions that will come up just like that and you may not need to answer them for your project. The takeaway is to understand that the problems you will have to solve when designing in the browser will require you to add some new tools to your toolbelt...and learn which one to use and when.

Don't Skimp on Preparation

Code savvy designers should be aware that jumping to code too soon is no different than jumping into your favorite design tool too soon. Do your research, draw out your sketches, and whatever else you need to get the information to solve the design problem at hand. If you're not prepared and ready then it doesn't really matter which process you follow as both will yeild less than ideal results. For designers that aren't as code savvy do know that it's easy to get lost in the weeds or get ahead of yourself while getting acquainted with the change in tools and process. So, you may find that you've foregone some preparation simply by accident but it happens and it's nothing to freak out about...well, at least not after the first time or two.

Keep your prep work a priority and by all means use whatever tool you need to create your best work. Over time as you become more familiar with new tools and technologies in your toolbelt and adjustments in your process you may find that you can actually create better user experiences and designs than ever before.

On a recent project, we'd been using jQuery DataTables (jQDT) rather extensively to handle super easy table data manipulation. A business requirement arose that requested we apply similar filtering, sorting, and paging to a NON-tabular view. Specifically, we were required to use jQDT to handle the data manipulation. I mean, we get this for free with this plugin, so why not use it, amirite?

The wireframes and mockups also required that we create a rather slick and robust filtering/sorting flyout, that ALSO had to integrate with the jQDT plugin. We couldn't just use the out of the box DOM API within jQDT So, I set out looking for the other cases where this had been done using this plugin. Nada.

ICanHaz.js to the rescue (big up to @knewter for introducing me to this little library). I also need to give a ton of props to the jQDT forums, as they were a wealth of information for writing/using jQDT plugins with the plugin API. This allowed me to access the plugin via external controls (ie, from that filtering/sorting flyout, jQuery UI datepicker, and more).

ICanHaz.js with Mustache

ICanHaz makes it STUPID simple to take in data and push it to a Mustache template (in this case, our templates are built in HAML), which is the basis for what I needed to do..

I went ahead and set up my template, taking care in some interpolation instances to wrap the property thrice for non-html encoding; like so:

{{{render_me_as_html_please}}}

Let's jump right into code, and take a look at what's going on.

Getting the table data

We need to get our data and prepare it for use to pass into ICanHaz. Why must we "prepare" the data you ask? Well, the table data is returned as arrays of arrays that contain prototypal properties to represent the column keys. Have I lost you yet? Don't worry, it took me a while to realize what was going on with the data. Here is a screenshot from Chrome Dev Tools showing what I am referring to with the data.

jQuery DataTable returned row data example

Now for the code to make this bad boy work and get it into a more useful data format (e.g. JSON):

  var tableData = table.fnGetFilteredData();
  $.each(tableData, function(i, data) {
    var row = {};

    // get the array of properties that are on the datatable data array (silly,
    // i know, but that's how this plugin returns its data from fnGetData and
    // similar api methods)
    var propertyArray = [];
    for (var k in data) {
      if (data.hasOwnProperty(k))  {
        propertyArray.push(k); 
      }
    }

    // loop through our array of properties and build proper array of objects so
    // that icanhaz and mustache can comprehend and use the data to populate our
    // template
    $.each(propertyArray, function(i, val) {
      row[val] = data[val];
    });
    rows.push(row);

    // send our row data to ICanHaz so it can create the mustache template
    // instances with our data
    accessory = ich.accessory(rows[i]);
    accessories.append(accessory);
  });

So, you remember me mentioning the way jQDT pulls in data? You can see here, I'm having to get the property name to access the data that is stored on the array (it's treating the array like an object literal).

As a sidenote, I couldn't simply use getOwnPropertyNames(); as this is not a supported object method in IE8 (and we had to give full UI/functional support back to IE8).

A couple final notes. The datatable container and datatable itself couldn't be hidden in the DOM. I had to position it absolutely out of the viewport. I'd like to re-investigate this project and see if there is a better way of handling this. As it stands now, you have both the actual table in the HTML, as well as your templated layout. Double the data, and markup. :/

This blog post will cover how to write JavaScript that is easier to maintain inside of a Ruby on Rails application. The following technique is what I use whenever writing JavaScript for a Rails application now. It uses JavaScript Objects to provide application specific objects and methods.

First assume there exists an application called MyApp and it has requirements defined for managing users and a blog. Also assume the requirement calls for a spinner upon submitting object data to the controllers. To satisfy this requirement assume spin.js has been chosen as the spinner library.

In the past, when I was more of a newbie, I would have gone to each view page that called for a spinner and would have written something as follows...

The wrong way

app/views/users/create.html.erb

<script type='text/javascript'>
  $(document).ready(function() {
    var opts = {
      lines: 13, // The number of lines to draw
      length: 7, // The length of each line
      width: 4, // The line thickness
      radius: 10, // The radius of the inner circle
      corners: 1, // Corner roundness (0..1)
      rotate: 0, // The rotation offset
      color: '#000', // #rgb or #rrggbb
      speed: 1, // Rounds per second
      trail: 60, // Afterglow percentage
      shadow: false, // Whether to render a shadow
      hwaccel: false, // Whether to use hardware acceleration
      className: 'spinner', // The CSS class to assign to the spinner
      zIndex: 2e9, // The z-index (defaults to 2000000000)
      top: 'auto', // Top position relative to parent in px
      left: 'auto' // Left position relative to parent in px
    };
    $('input#submit-button').click(function() {
      var target = document.getElementById('my-spinner');
      var spinner = new Spinner(opts).spin(target);
    });
  });
</script>

app/views/posts/create.html.erb

<script type='text/javascript'>
  $(document).ready(function() {
    var opts = {
      lines: 13, // The number of lines to draw
      length: 7, // The length of each line
      width: 4, // The line thickness
      radius: 10, // The radius of the inner circle
      corners: 1, // Corner roundness (0..1)
      rotate: 0, // The rotation offset
      color: '#000', // #rgb or #rrggbb
      speed: 1, // Rounds per second
      trail: 60, // Afterglow percentage
      shadow: false, // Whether to render a shadow
      hwaccel: false, // Whether to use hardware acceleration
      className: 'spinner', // The CSS class to assign to the spinner
      zIndex: 2e9, // The z-index (defaults to 2000000000)
      top: 'auto', // Top position relative to parent in px
      left: 'auto' // Left position relative to parent in px
    };
    $('input#submit-button').click(function() {
      var target = document.getElementById('my-other-spinner');
      var spinner = new Spinner(opts).spin(target);
    });
  });
</script>

To make this better I use JavaScript objects and dependency injection to reuse this spinner whenever I need it (DRY right?).

The right way

First we'll make a base object in JavaScript that will provide a nice application specific object for our application:

app/assets/javascripts/my_app_base.js

// This is just an object so we have a place to put things
// and only add a single global.
window.MyApp = {};

Now we can make our reuseable spinner object:

app/assets/javascripts/my_app_spinner.js

MyApp.spinner = function(target, event_target, evt){
  var spin_it = function(target) {
    var opts = {
      lines: 13, // The number of lines to draw
      length: 7, // The length of each line
      width: 4, // The line thickness
      radius: 10, // The radius of the inner circle
      corners: 1, // Corner roundness (0..1)
      rotate: 0, // The rotation offset
      color: '#000', // #rgb or #rrggbb
      speed: 1, // Rounds per second
      trail: 60, // Afterglow percentage
      shadow: false, // Whether to render a shadow
      hwaccel: false, // Whether to use hardware acceleration
      className: 'spinner', // The CSS class to assign to the spinner
      zIndex: 2e9, // The z-index (defaults to 2000000000)
      top: 'auto', // Top position relative to parent in px
      left: 'auto' // Left position relative to parent in px
    };

    var spinner = new Spinner(opts);
    spinner.spin(target[0]);
  }

  target = $(target);
  event_target = $(event_target);

  event_target.on(evt, function(e) {
    spin_it(target);
  });
}

And now the view pages are a lot less cluttered with repeated JavaScripts:

app/views/users/create.html.erb

$(document).ready( new MyApp.spinner($('#my-spinner'), $('#submit-button'), 'click') );

app/views/posts/create.html.erb

$(document).ready( new MyApp.spinner($('#my-other-spinner'), $('#submit-button'), 'click') );

Things to note

For this particular instance, notice that we can pass any DOM/jQuery element to the spinner object with an event to bind to that object and the spinner object. These dependencies are chosen (or injected) at runtime. This is one element aiding cleaning up the code by removing the hard-coded dependencies.

About_josh_adams

January 18th, 2013 09:40

Linkdump! To the knowledge:

About_josh_adams

December 21st, 2012 10:21

It's that time again! LINKS!