Tuesday Tricks - Regex Posix Shortcuts

Hate typing redundant regular expressions? Me too. How often have you typed the regex [a-zA-Z0-9]?

Posix character classes are here to save the day. You can replace a-zA-Z0-9 with [:alnum:]. [:alnum:] is the posix character class and there's a whole slew of them at your disposal. Use them in Ruby like so:

'-- I have 37 dollars --' =~ /[[:alnum:]]/ #=> 3
'-- I have 37 dollars --' =~ /[[:digit:]]/ #=> 10
'-- I have 37 dollars --' =~ /[[:space:]]/ #=> 2

Note: An expression with =~ returns the first position in the string which matches the regex.

Check out the full list of posix character classes and determine how you can prettify your expressions.

This Tuesday's Trick

Posix character classes won't prevent global warming but they sure can help make your regular expressions more readable.

Posted by Mike Pack on 06/28/2011 at 01:20PM

Tags: regex, ruby, posix


Testing Mobile Rails Apps with Capybara

Every web app should have a mobile version and every mobile version should be tested. Testing mobile web apps shouldn't be any more painful than testing desktop apps with the assumption that you're still serving up HTML, CSS, and JavaScript.

My Setup

For mobile detection, I use ActiveDevice, a User Agent sniffing library and some helper methods. While User Agent sniffing isn't the best approach for client-side (use feature detection with something like Modernizr), it's a reliable way to detect mobile devices in Rails.

For acceptance testing that doesn't need to be readily demonstrated to stakeholders, I use straight up Capybara with RSpec. Sometimes I use Steak.

The Pain of Testing Mobile

It's difficult to test mobile web apps because Capybara's default drivers are all desktop User Agents. You could acquire Capybara-iphone, but this solution didn't produce the expected results for me. I was given my mobile views but not my mobile layout. Plus, all this driver does is reset the User Agent for the Rack-Test driver. Further, what if you use Selenium for your default driver?

Platformatec wrote a nice blog post about mobile testing with user agents. The problem is it relies on Selenium. I was seeking a more concrete, driver agnostic way to serve up mobile views to my tests.

How I Test Mobile

This is a simple, straightforward way to invoke your mobile app from within your tests. I'm not convinced it's the most elegant way, but it's clean and simple.

Setup Your Application

In your ApplicationController, give some support for changing over to  your mobile app. This will also come in handy when you want to work on and test your mobile app on your desktop browser.

app/controllers/application_controller.rb

@@format = :html
cattr_accessor :format

Here we simply add a class attribute accessor with a default of :html. This will allow us to say ApplicationController.format

Next we need to add a before filter which will set the desired format upon each request.

app/controllers/application_controller.rb

before_filter :establish_format

private
def establish_format
  # If the request is from a true mobile device, don't set the format
request.format = self.format unless request.format == :mobile
end

Here's what a sample Rails 3 ApplicationController would look like:

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  include ActiveDevice

  # force the mobile version for development:
  #@@format = :mobile
  @@format = :html
  cattr_accessor :format
  before_filter :establish_format

private
  def establish_format
# If the request is from a true mobile device, don't set the format
request.format = self.format unless request.format == :mobile
end
end

Setup Your Tests

Now, in your tests, you can set the desired format for your application.

spec/integration/mobile/some_spec.rb

require 'spec_helper'

describe 'on a mobile device' do
  before do
    ApplicationController.format = :mobile
  end

  after do
    ApplicationController.format = :html
  end

  describe 'as a guest on the home page' do
    before do
      visit root_path
    end

    it 'does what I want' do
      page.should do_what_i_want
    end
  end
end

By setting ApplicationController.format = :mobile, we force the application to render the mobile version of files, for instance: index.mobile.erb. Your application will be invoked, your before filter will be run, and your are serving the mobile app to your tests.

Note: You need to reset your format to :html after your mobile tests are run so that tests which follow this in your suite are run under the default format, :html.

Happy testing!

Posted by Mike Pack on 06/16/2011 at 11:05AM

Tags: rails, testing, rspec, capybara, mobile


New/Scope Safe Constructors in OO JavaScript

One frequent problem when developing in Object Oriented JavaScript is how to handle the removal of the "new" keyword when creating an instance of a class. It's often expected that an object should be viably instantiated two ways, with the "new" keyword and without.

var part1 = new CarPart('Wheel');
var part2 = CarPart('Axel');

With a normal constructor, the above code won't act as expected. Assume our CarPart constructor looks as follows:

function CarPart(name) {
  this.name = name;
}

Since this is bound at runtime, omitting the new operator results in a late binding to the window object. Late binding in JavaScript is often resolved with the use of closures but can't be in this case. In the case where the new operator is omitted, this.name is effectively the same as window.name.

Creating new/scope safe constructors is very important. If you write a library, for instance, it can't be expected that all users will be familiar enough with OO JavaScript to include the new operator. As the creator of a library, a good API results in a certain degree of permission for users to do what they want. Constructors are a good example of such a permission.

How to fix that poor constructor

Our goal is to identify when the constructor was called without the new operator and then invoke the constructor properly. Observe the following code.

function CarPart(name) {
if(this instanceof CarPart) {
  this.name = name;
} else {
return new CarPart(name);
}
}

In this code, we evaluate if the this object is a CarPart and proceed as normal. If the this object is not a CarPart (ie, it's a window object), call the constructor again, this time with the new operator.

Now our constructor works properly with or without the new operator.

But what about inheritance?

Close observers would realize that a child of the CarPart class would not be able to successfully invoke the parent constructor because it assumes the caller is a CarPart. In the following example, our safe constructor (CarPart) will not set the name attribute on the Wheel object. It would instantiate a new CarPart.

function CarPart(name) {
if(this instanceof CarPart) {
  this.name = name;
} else {
return new CarPart(name);
}
}

function Wheel(radius) {
CarPart.call(this, 'Wheel');
this.radius = radius;
}

Note: Wheel should be made new/scope safe as well.

In the above example, within the Wheel constructor, CarPart.call is what invokes the parent constructor, known as constructor stealing. When CarPart's constructor is called, this instanceof CarPart will fail because this is an instance of Wheel.

The solution to this problem lies within the Wheel's prototype. If we set the following after the declaration of Wheel, the inheritance chain is correctly established and this instanceof CarPart will return true if this is a Wheel.

Wheel.prototype = new CarPart();

Happy constructing!

Posted by Mike Pack on 05/23/2011 at 10:29AM

Tags: javascript, oo, inheritance