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 :)
- 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
draperwe were using on a project by a major version, and usedbetter_errorsto figure out the API changes without reading too much documentation fordraper
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
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)
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);
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;
return
a + b
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.
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.
- Know your stuff
- Right tool for the job
- 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.

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.
Linkdump! To the knowledge:
- git-pivotal-hooks - tie your git into your pivotal tracker.
- Broadway got multi-process support - so Broadway is a rendering engine for gtk that outputs to http/canvas. If you've not seen it before, watching this video will be a treat (if you're into awesome things)
- Wacky is a Rails engine for painlessly embedding a wiki in your rails app. It's very basic. We developed it to be our internal wiki, and we think it would be a good idea for you to use it too :)
- SVG Path Morphing - this is one of the neatest things I've ever seen done with SVG :)
- pelusa - lint your Ruby code to improve your OOP skills.
- 3d printed quadcopter frame - I just got a makerbot replicator2 yesterday, so this is on my list of things to print now :)
- Revisiting JavaScript Objects - an article with lots of nice things you can do in javascript in most deployed browsers today, that you likely aren't taking advantage of (I wasn't, and I write a lot of javascript)
- Obvious is a clean architecture framework. I've not yet built an app with this framework, but I desparately want to. I read through one.
- helium is "a tool for discovering unused CSS across many pages on a web site."
- visual event - see javascript events that have been attached to DOM elements
- On Antifragility in Systems and Organizational Architecture - I've not yet read Antifragile but this post made me really badly want to. Good.
- Awesome table built with pipe
- Rails devops cheatsheat
- Asset Pipeline Internals
- form follows function this is amazing. CSS experiments gone right.
- Android Mini PC RK3066
- The language of languages and hn discussion
- Notes on Distributed Systems for Young Bloods
- The Deep Synergy Between Testability and Good Design
- spanish inquisition - simple ruby survey DSL
- 360 degree panoramic video from the stratosphere - You Will Not Be Disappointed.
It's that time again! LINKS!
- Netzke - client server components with Sencha, ext.js, and Ruby
- Ratchet - prototype iphone app designs with html/css easily
- Ruboto - build and package android applications with ruby
- Android Scripting Layer
- wizardwerdna reworked Avdi's Objects On Rails, but in Bob Martin's Clean Architecture - This is probably the most awesome link in this linkdump. Still unsure when it's proper / useful to actually build an app out this way from the start. I guess if you're used to it, then the cost isn't too high.
- Moonbase - Graphical programming sort of - very nice js project
- Awesome dribbble #1
- Awesome dribbble #2
- PEG.js - Need to build a parser in javascript using Parsing Expression Grammar formalism? This is your boy.
- Respond.js - A fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more)
- ql.io - A DECLARATIVE, DATA-RETRIEVAL AND AGGREGATION GATEWAY FOR QUICKLY CONSUMING HTTP APIS
- acorn - A small, fast, JavaScript-based JavaScript parser
- jsfsm - A JavaScript finite state machine
- FastBook - because HTML5 is fast enough dangit
- How to read macros
- analytics.js - The hassle-free way to integrate analytics into any web application
- MathBox.js - Make presentation-quality math diagrams in WebGL