Episode #457 - April 18th, 2014

Posted 3 days back at Ruby5

URL parsing with Rippersnapper, awesome APIs with Pliny, thread-safe utilities from Charles Nutter, a revival of the invoicing gem, info about recursion and memoization, querying git with gitql, and refactoring bad controllers all in this episode of the Ruby5 podcast!

Listen to this episode on Ruby5

Sponsored by New Relic

New Relic is _the_ all-in-one web performance analytics product. It lets you manage and monitor web application performance, from the browser down to the line of code. With Real User Monitoring, New Relic users can see browser response times by geographical location of the user, or by browser type.
This episode is sponsored by New Relic

Rippersnapper

Working with URLs in your app has never been easier with Rippersnapper. Give it a URL and get back all your favorite parts!
Rippersnapper

Pliny

Base Sinatra app for writing excellent APIs in Ruby.
Pliny

thread_safe

A collection of utilities for thread-safe programming in Ruby.
thread_safe

Invoicing

Before you roll your own invoicing framework, have a look at the invoicing gem from Codemancers. It might be just want you need!
Invoicing

Recursion and Memoization

Ray Hightower on avoiding the some recursion performance pitfalls in Ruby with memoization.
Recursion and Memoization

gitql

A git query language. Such git! So query!
gitql

Refactoring Controllers

Ever needed to refactor a bad controller? Justin Weiss walks you through his process in this new blog post.
Refactoring Controllers

Swirrl and the ODI

Posted 3 days back at RicRoberts :

ODI logo

Some great news - we’ve recently become members of the Open Data Institute. Founded in 2012 by Sir Tim Berners-Lee and Professor Sir Nigel Shadbolt, the ODI is an independent, non-profit, non-partisan, limited by guarantee company. And they’re all about promoting innovation and collaboration when it comes to Open Data, not only in the UK but around the world.

So we’re happy as sand boys (and girls) to be members of an organisation that shares our passion for data. And, if that wasn’t enough, we’re also working with the ODI on the European DaPaaS project that we recently blogged about.

You can find us in their member directory and, of course, we’re always here if you want to get in touch.

Mid-Senior Ruby on Rails Developer up to 60K central London

Posted 4 days back at Ruby on Rails, London - The Blog by Dynamic50

Hiring a Mid-Senior Ruby on Rails Developer. You will be an experienced Ruby and Rails engineer with the opportunity to work in central London with a great company.


Essential skills
Ruby
Rails
Exposure to Rack Middleware and implementation
Gems
RSpec/Cucumber/Capybara
Creating /Consuming RESTful API’s
GIT


Experience that would be Nice to have
Cloud -AWS, Heroku
Elastic Search, Lucene, Solr
 

Central London, great company!


up to 60K based on experience


Get in touch now alex.tealdi@dynamic50.com 020 3286 2879

DaPaaS: simplifying open data publishing and use

Posted 5 days back at RicRoberts :

DaPaas logo

Towards the end of last year, we started work on a European collaborative project called DaPaaS (Data-and-Platform-as-a-Service). It aims to optimise and simplify both publication and use of Open Data across different platforms.

Being part of this is great for us because it’s very well aligned to our development objectives for our PublishMyData platform.

Our main role in the project is to simplify data publishing for non experts. So, we’ll be developing tools to help users create and publish Linked Data themselves. And we’ll also be working towards creating a clear methodology for data publishing that can be used in the DaPaaS system. Exciting stuff, because it’ll make Linked Data more accessible to people who don’t usually work directly with the advanced, techy side, which is one of our goals.

But the good stuff doesn’t end there. We’re fortunate to be working with some really talented people on this project including our friends at the ODI. The full list of project partners is:

You can read more about DaPaas and our consortium on the project website.

Test Driving iOS - A Primer

Posted 5 days back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

In case you missed it, our own Britt Ballard (a fellow native Texan) published a fantastic post in our Back to Basics series on test-first methodology. My only issue with it is that the entire post is written in this super obscure language called Ruby! So I wanted to take a look at the same methodology from the point of view of an iOS developer, in tried and true Objective-C.

Our desired code

We would like to build a system that includes the following:

  • A category method for reversing strings
  • A custom UITableViewCell subclass with a method that:
    • Takes a string
    • Reverses the string
    • Sets the string as the text on its label

Tools and techniques

We're going to use the same techniques as laid out in Britt's post. We'll use red/green/refactor methodology, and we'll write unit tests that are fast, isolated, repeatable, self-verifying, and timely. But instead of using RSpec, we're going to use Specta and Expecta to test our method's output. These are modular spec and matcher frameworks (respectively) that make XCTest not horrible. We'll also use OCMock to mock out any external dependencies we might run into.

A quick aside on using Specta

Assuming you're using CocoaPods, you'll want to create a group inside your Podfile for our dependencies:

target :unit_tests, :exclusive => true do
  link_with 'UnitTests'
  pod 'Specta'
  pod 'Expecta'
  pod 'OCMock'
end

This will keep our testing dependencies out of our main bundle, and the :exclusive => true flag will keep any normal dependencies out of our testing bundle. This is to avoid duplicate symbols when the testing bundle is injected into the host application.

Specta has a syntax you might not be immediately familiar with. I highly recommend installing their file templates, but all you really need to know is that instead of your normal pattern for defining a class:

@implementation MyTestClass : XCTestCase

// Tests go here

@end

Specta uses some nifty macros to clean things up:

SpecBegin(ClassUnderTest)

// Tests go here

SpecEnd

Convention (stolen from Ruby) says that we should name our spec files ClassUnderTestSpec.m. Specs for categories will be named FoundationClass_ExtensionSpec.m. We don't need public headers for specs.

The testing syntax itself is very block heavy. But other than that, it follows RSpec's syntax almost exactly.

The category method: Starting with the desired end state

We'll start in the same place as we would in Ruby. Given a string ("example string"), we expect to be able to call a method to get a reversed version of that string ("gnirts elpmaxe"):

// NSString_ReversedSpec.m

#import "NSString+Reversed.h"

SpecBegin(NSString_Reversed)

describe(@"NSString+Reversed", ^{
    it(@"reverses strings", ^{
        NSString *originalString = @"example string";

        NSString *reversedString = [originalString reversedString];

        expect(reversedString).to.equal(@"gnirts elpmaxe");
    });
});

SpecEnd

Now, here's where Ruby and Objective-C diverge a bit. If we look at Britt's original post, this is when he starts running the tests. But since we have a compiler, and Xcode generates warnings and errors in real time, we're able to lean on those a bit to get us moving forward.

Right now we should have 2 errors displayed:

  • 'NSString+Reversed.h' file not found for our #import statement
  • No visible @interface for 'NSString' declares the selector 'reversedString'

This is the roadmap for our first few steps. Looking at the errors, we can see that we need to do 2 things:

  • Create a new Reversed category on NSString
  • Define a public reversedString method for that category

Let's go ahead and take care of the first one:

// NSString+Reversed.h

@interface NSString (Reversed)
@end

// NSString+Reversed.m

#import "NSString+Reversed.h"

@implementation NSString (Reversed)
@end

Once Xcode catches up, we should see one of the errors disappear. The only remaining error is telling us that we need to define reversedString. We know by looking at the usage that it's going to need to return an NSString. So let's go ahead and declare it:

// NSString+Reversed.h

@interface NSString (Reversed)

- (NSString *)reversedString;

@end

And hey! Just like that, we've gotten rid of all of the errors that were preventing us from building. But there's still one more thing we can use the compiler to lead us to, before actually running the tests.

Once the errors went away, we should have seen a warning pop up (you might have to build the project to get Xcode to catch up). The warning tells us that while we're saying that NSString has a method named reversedString, there isn't actually any implementation for a method with that name anywhere. Let's implement that method just enough to get rid of the warning:

// NSString+Reversed.m

#import "NSString+Reversed.h"

@implementation NSString (Reversed)

- (NSString *)reversedString
{
    return nil;
}

@end

Blam. No warnings, no errors. We haven't run the tests once, but we've used the compiler to help us get to the point where we know that our class is set up the way we said it would be. Let's finally run the tests! I recommend getting used to smashing ⌘U in Xcode. It's a handy shortcut. In the test navigator we see the failure:

And we see the error inline:

expected: gnirts elpmaxe, got: nil/null

So now we know that everything is hooked up properly, but we aren't returning the right thing. Let's make the test pass with the least amount of work possible:

// NSString+Reversed.m

#import "NSString+Reversed.h"

@implementation NSString (Reversed)

- (NSString *)reversedString
{
    return @"gnirts elpmaxe";
}

@end

And now we have our first passing test!

Refactoring

Returning a hardcoded value got our tests to pass, but it surely isn't what we want in production. It's pretty obvious that this method won't work for any string value, but now that we've gotten our test suite (small that it may be) to green, we can use it to help us complete the implementation without changing the expected behavior:

// NSString+Reversed.m

#import "NSString+Reversed.h"

@implementation NSString (Reversed)

- (NSString *)reversedString
{
    NSMutableString *reversedString = [NSMutableString string];

    NSRange range = NSMakeRange(0, [self length]);
    NSStringEnumerationOptions options = (NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences);

    [self enumerateSubstringsInRange:range
                               options:options
                            usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                                [reversedString appendString:substring];
                            }];

    return [reversedString copy];
}

@end

Now we have a nice method that we can use on any NSString instance that will return a reversed version of that string, and the whole thing is backed by tests!

UITableViewCell subclass

We start our journey the same as before. We'll state our expected behavior and then work towards getting a clean build, and a green test suite.

We'll start with the initial requirement of reversing the string provided to the method. We're going to use a mock object to ensure that we're only dealing with our Foundation class and the class under test:

// TBReverseStringCellSpec.m

#import "TBReverseStringCell.h"

SpecBegin(TBReverseStringCell)

describe(@"TBReverseStringCell", ^{
    it(@"reverses the string provided to it", ^{
        TBReverseStringCell *cell = [TBReverseStringCell new];
        id stringMock = [OCMockObject mockForClass:[NSString class]];
        [[stringMock expect] reversedString];

        [cell setReversedText:stringMock];

        [stringMock verify];
    });
});

SpecEnd

Right away, we notice that we've got a few errors to deal with. We'll start by creating the class itself:

// TBReverseStringCell.h

@interface TBReverseStringCell : UITableViewCell
@end

// TBReverseStringCell.m

#import "TBReverseStringCell.h"

@implementation TBReverseStringCell
@end

Now we're left with the warning about the undeclared selector, so we'll fix that:

// TBReverseStringCell.h

@interface TBReverseStringCell : UITableViewCell

- (void)setReversedText:(NSString *)string;

@end

And now we're left with that same warning about the missing definition for setReversedText:. Once again, we're only going to add enough code to get our project to build cleanly. In this case, that means creating an empty method definition:

// TBReverseStringCell.m

#import "TBReverseStringCell.h"

@implementation TBReverseStringCell

- (void)setReversedText:(NSString *)string
{
}

@end

Now that our build is clean, we can run our tests, and get some meaningful feedback:

test failure: -[TBReverseStringCellSpec TBReverseStringCell_reverses_the_string_provided_to_it] failed:
OCMockObject[NSString]: expected method was not invoked: reversedString

So let's go ahead and fix that test:

// TBReverseStringCell.m

#import "TBReverseStringCell.h"
#import "NSString+Reversed.h"

@implementation TBReverseStringCell

- (void)setReversedText:(NSString *)string
{
    [string reversedString];
}

@end

And now our suite is green again. We can move on to our final requirement, that the cell sets the reversed string value on the internal label:

// TBReverseStringCellSpec.m

it(@"sets a string value on the internal label", ^{
    TBReverseStringCell *cell = [TBReverseStringCell new];
    id labelMock = [OCMockObject mockForClass:[UILabel class]];
    cell.reverseLabel = labelMock;
    [[labelMock expect] setText:@"gnirts elpmaxe"];

    [cell setReversedText:@"example string"];

    [labelMock verify];
});

Again, a build error because of a missing part of our public interface, so that's our first step:

// TBReverseStringCell.h

@interface TBReverseStringCell : UITableViewCell

@property (nonatomic) UILabel *reverseLabel;

- (void)setReversedText:(NSString *)string;

@end

With our build clean, we can see what we need to to to fix the test:

test failure: -[TBReverseStringCellSpec TBReverseStringCell_sets_a_string_value_on_the_internal_label] failed:
OCMockObject[UILabel]: expected method was not invoked: setText:@"gnirts elpmaxe"

A quick modification to our implementation gets us to our desired result:

// TBReverseStringCell.m

- (void)setReversedText:(NSString *)string
{
    NSString *reverseString = [string reversedString];
    self.reverseLabel.text = reverseString;
}

And there we have it. We were able to satisfy our requirements, and we did it by leading ourselves with tests. This example is simple and contrived, but this same pattern can be applied to requirements of any size.

What's next?

If you're excited about using TDD in your app, you should check out:

Episode #456 - April 15th, 2014

Posted 6 days back at Ruby5

In this episode we cover the results of the Cloudflare Heartbleed challenge, tracking trends in the Ruby community with the Ruby Survey, Rails 4.1 ActiveRecord enums, iStats for CPU temperature on OS X and some Insanely Useful ActiveAdmin Customizations.

Listen to this episode on Ruby5

Sponsored by ElixirSips

If you're interested in learning Elixir, but don't know where to start, then ElixirSips.com is perfect for you. It's two short screencasts each week - between 5 and 15 minutes each. ElixirSips currently consists of over 7 hours of densely packed videos, and there are more every week.
This episode is sponsored by ElixirSips

Heartbleed Verified

Last Friday, CloudFlare set up a honeypot server and invited the world to steal their private SSL keys. The goal was to prove their disbelief that private SSL keys were vulnerable to the Heartbleed security breach. The result was that two different people were able to steal their private SSL keys before the end of the day. Those individuals proved it to CloudFlare by sending them back their private SSL keys in an email.
Heartbleed Verified

Ruby Survey

The Ruby Survey for 2014 was recently posted, and the objective of the survey is to track trends in the Ruby community. If you are curious about the result for previous years, they are available on the website as well.
Ruby Survey

Enums

Andrea Longhi put together an article on Rails 4.1 ActiveRecords enums. She shows the methods that are automatically created for us, and points out how if we try to make an enum which is a reserved word, ActiveRecord is smart enough to explode.
Enums

iStats

iStats is a Ruby gem that displays the temperature for your computer's CPU. The gem is a Ruby wrapper for a small C library that interacts with Apple's IOKit library.
iStats

ActiveAdmin Customizations

Mike Ackerman’s wrote an article on Viget labs last Friday where he covers eight insanely useful ActiveAdmin customizations. Mike details how to add custom logic to your admin controllers, add query scoping to disallow some people from seeing *All The Things*, manipulate top-­level menus, display images in upload forms, and more.
ActiveAdmin Customizations

Refactoring Ruby Iteration Patterns to the Database

Posted 6 days back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Frequently on projects we need to run a calculation through an ActiveRecord association. For example, we might want to get a user's all time purchases, a company's total amount of products sold, or in our case, the total amount of loans made to a campaign. This sort of calculation is ripe for using a map and an inject but frequently the solution is more elegant and faster if we can have SQL do the work instead.

Here is what our domain looks like.

class Campaign < ActiveRecord::Base
  has_many :loans
end

class Loan < ActiveRecord::Base
  belongs_to :campaign
end

The goal

We want to be able to ask a campaign how much money it has raised. An initial implementation might look like this.

class Campaign < ActiveRecord::Base
  # ...
  def funds_raised
    loans.map(&:amount).inject(:+)
  end
end

We are using the association to get the campaign's loans and then summing up the amount of each loan. If we look at our logs we'll see that the SQL generated is grabbing all of the loans for our campaign and pulling them into memory.

SELECT "loans".* FROM "loans" WHERE "loans"."campaign_id" = <target_campaign_id>

Then in Ruby (at the application layer), we run the map to get the amounts and the inject to get the sum. Done. Not that bad but we can do better.

Using SQL sum

We want to avoid pulling all this data into memory just to get a single number. Let's have the database do the heavy lifting.

class Campaign < ActiveRecord::Base
  # ...
  def funds_raised
    loans.sum(:amount)
  end
end

With this implementation we have the database do the calculation. We get access to sum from ActiveRecord. Check out the docs for more details.

Looking at the logs we can see the following SQL.

SELECT SUM("loans"."amount") AS sum_id FROM "loans" WHERE "loans"."campaign_id" = <target_campaign_id>

This SQL is going to give us the same answer but in a single step. Through this refactoring we have code that is easier to read, we use less application memory, and we see a performance boost because we're pushing the calculation down to the database. Based on benchmarks where each campaign has 1000 loans, the sum approach can be more than 20x faster than using map / inject.

Next time we reach for a map and inject on associated ActiveRecord objects, we'll check to see if there is a way to have the database do the work instead.

What's next?

If you would like some more background on additional SQL aggregate functions check out the following articles:

For some more information about Ruby's Enumerable class and Enumerable#inject in particular, check out:

Smart Data Hack Edinburgh

Posted 7 days back at RicRoberts :

In February, our very own Bill went to advise at the Smart Data Hack in Edinburgh. This was a 5 day event that involved undergraduates splitting into 16 teams to make apps using open data. Ewan Klein arranged it; it was well attended and, eager to encourage our love of data and its uses, we put up a prize of £250 for the best app that used government data.

And Bill said competition was high - you can read more detail on the different projects here but the winning team was called Go4itPrincess with their MSP Involvement Project. Their app examines how much Scottish Members of Parliament speak up and on what topics. It then aims to analyse any correlation between that and their constituency’s rankings on the Scottish Index of Multiple Deprivation. Pretty creative data use - kudos princess(es?)!

And projects aside, one of the things that Bill found most impressive was that the students could get to grips with SPARQL for extracting their data. And they were generally happier retrieving data from APIs than having to download files and manage them themselves - showing just how accessible API use can be.

If you want to get more of an insight about the hackathon, check out tweets from the event and the screenshots below (thanks to the OKF Scotland blog), which show some of the great apps created.

CareForEd project:

MSP Involvement project:

Shoulda Matchers 2.6.0

Posted 7 days back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

For the past four months, we've been hard at work on the next version of shoulda-matchers, and we're pleased to announce it's up on RubyGems.

2.6.0 is first and foremost a compatibility release, bringing a few of the matchers up to date with the newest changes in Rails 4.1. However, there are also some new matchers for you to use.

The following is a brief highlight; there are plenty of changes we made, so read the NEWS file for the full scoop.

Matchers restored from 2.0.0

If you remember, when we released 2.0.0, we decided to remove a couple of matchers as we hadn't quite polished them enough. They're now back!

You can now use the permit matcher for testing usage of strong parameters in your controller:

class UserController < ActionController::Base
  def create
    User.create(user_params)
  end

  private

  def user_params
    params.require(:user).permit(:email)
  end
end

# RSpec
describe UserController do
  it { should permit(:email).for(:create) }
end

# Test::Unit
class UserControllerTest < ActionController::TestCase
  should permit(:email).for(:create)
end

You can also use delegate_method for usage of Rails's delegate method or other forms of delegation:

class Human < ActiveRecord::Base
  has_one :robot
  delegate :work, to: :robot

  # alternatively, if you are not using Rails
  def work
    robot.work
  end

  def protect
    robot.protect('Sarah Connor')
  end

  def speak
    robot.beep_boop
  end
end

# RSpec
describe Human do
  it { should delegate_method(:work).to(:robot) }
  it { should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor') }
  it { should delegate_method(:beep_boop).to(:robot).as(:speak) }
end

# Test::Unit
class HumanTest < ActiveSupport::TestCase
  should delegate_method(:work).to(:robot)
  should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor')
  should delegate_method(:beep_boop).to(:robot).as(:speak)
end

Callback matchers

There are also some new matchers for testing callbacks in controllers:

  • use_before_filter
  • use_after_filter
  • use_around_filter

These are aliased as use_<callback>_action, for consistency with the renamed callback macros in Rails 4.

class UserController < ActionController::Base
  before_filter :authenticate_user!
end

# RSpec
describe UserController do
  it { should use_before_filter(:authenticate_user!) }
end

# Test::Unit
class UserControllerTest < ActionController::TestCase
  should use_before_filter(:authenticate_user!)
end

ensure_inclusion_of works with boolean columns (with caveats)

This issue has evaded us for a while. The fix was not straightforward and we ultimately ended up making a couple of compromises.

One case this fix addressed was testing that a boolean column accepts true or false or both. If you say that a boolean column only accepts true, you have to test that it can't accept false; if you specify that it only accepts false, you have to test that it can't accept true. That part's easy:

class Issue < ActiveRecord::Base
  validates_inclusion_of :open, in: [true]
  validates_inclusion_of :closed, in: [false]
end

describe Issue do
  it { should ensure_inclusion_of(:open).in_array([true])
  it { should ensure_inclusion_of(:false).in_array([false])
end

But what if a column can accept both true and false? What do you test? Well, there's no value that a boolean column can take other than true and false, so this sort of test is impossible to write:

class Issue < ActiveRecord::Base
  validates_inclusion_of :open, in: [true, false]
end

describe Issue do
  # This will work, but will give you a warning
  it { should ensure_inclusion_of(:open).in_array([true, false])
end

The other case addressed by this fix occurs if you have a boolean column which is non-nullable and you test that the column should accept nil as a value. This is also an impossible test because a non-nullable column, by definition, cannot accept nil; and because it's a boolean column in this case, as soon as you set it to nil it will get coerced to false.

create_table :issues do |t|
  t.boolean :open, null: false
end

describe Issue do
  # This will also work, but will also give you a warning
  it { should_not ensure_inclusion_of(:open).in_array([nil])
end

Other notable features and bugfixes

  • Association matchers gained the autosave option.
  • validate_numericality_of gained the allow_nil option.
  • belong_to gained the inverse_of option.
  • rescue_from now works with exception handler methods marked as protected or private.

Thank you

I'd like to thank the contributors that helped us with this release:

Enjoy!

Red Fox with Kit

Posted 8 days back at Mike Clark

Red Fox with Kit

It's good to finally see signs of spring!

What do you need to make a successful web app?

Posted 8 days back at mir.aculo.us - Home

Here’s some things you need to make a successful web app:

  • A plan to make an application that helps real people to make their lives easier, solving a well-researched problem
  • Understand human psychology
  • Know how design, both in terms of UX flow and visual design
  • A marketing plan, to tell potential customers that your app solves their problem
  • A text editor
  • A web server
  • Probably some sort of database
  • A payment processor of sorts
  • Good security from the start
  • An understanding of tax laws in your country
  • A healthy dose of perseverance

And here’s some things you don’t need:

  • The latest alpha of hype.js
  • CSS frameworks
  • Boilerplates
  • reset.css
  • JavaScript loaders
  • The newest NoNoNoSQL database
  • Distributed anything
  • That cool new jQuery plugin
  • A custom-designed font
  • Multiple load-balanced “webscale” servers

All these things create the illusion of making things easier when in reality they create very complex dependencies and will be very hard to remove later if they don’t turn out to be the silver bullets they promise to be. This doesn’t mean these things are bad or evil. You may want some of them later, when your app grows.

Remember, keep it simple and don’t over-engineer. Solve the problems at hand, and don’t anticipate “potential” problems.

You need to wear many hats when setting out to make a successful web application: entrepreneur, psychologist, designer, programmer, marketer, accountant—but you’re not a fortune teller.

Episode #455 - April 8th, 2014

Posted 10 days back at Ruby5

The internet is heartbleeding plus exciting rails 4.1 features. With special guest Nathan Hessler.

Listen to this episode on Ruby5

Sponsored by New Relic

You should be using New Relic by now, but do you regularly check out their blog?
New Relic

Heartbleed

The Heartbleed Bug is a serious vulnerability in the popular OpenSSL cryptographic software library. This weakness allows stealing the information normally protected with SSL/TLS encryption.
Heartbleed

tco gem

Radek Pazdera has released the TCO gem. It allows you to use simple RGB to choose terminal colors
tco gem

Ruby 2.1 Garbage Collection

Sam Saffron has posted an article titled Ruby 2.1 Garbage Collection: ready for production
Ruby 2.1 Garbage Collection

Hound

Thoughtbot has released Hound, a hosted service that comments on Ruby style guide violations in your GitHub pull requests.
Hound

3 features from Rails 4.1 that I’m excited about

Lucas Mazza has posted the 3 features from Rails 4.1 that he's excited about
3 features from Rails 4.1 that I’m excited about

Extract Mostly-Constant Data from the Database

Posted 10 days back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Using database-backed models in our applications can cause coupling and performance problems. Extracting that data to Ruby constants helps to resolve those problems.

Example

Consider the following database tables and their data:

  • subscription_plans (subscriber free, subscriber paid, group free, group paid)
  • countries (United States, India, Belgium, Uruguay, etc.)

This data change so rarely that for the purpose of the application, it is essentially constant. Representing the data in our database has the following drawbacks:

  • Code/database coupling
  • Slower performance

Code/database coupling

If we put constant data in the database, our code and the database will need to exist in a very specific shape at a given time.

Every environment (development, staging, production) will need to know the values and seed them into their respective databases.

When we need to deploy code changes, we may need to include a data migration to chande the data. Particularly in environments that gradually roll out features, this may complicate our development, git branching, and deploy processes by forcing us to consider questions such as:

  • Do we run the migration before or after the code changes are deployed?
  • During the roll out to a percentage of users and app servers, will both old and new code work on the migrated database or will one cohort get bugs?

Slower performance

While 99% of our traffic patterns should be served from our database cache, we will still be paying a small performance penalty for accessing the database across a network.

In comparison, if we move our data to constants in our application, we will already have it in memory when the application loads. There is essentially no performance hit to pull it from memory when we need it.

Solution: Constants and Plain Old Ruby Objects

Here is an example class that can replace the subscription_plans table:

class SubscriptionPlan
  def initialize(slug, name, braintree_id = nil)
    @slug = slug.to_s
    @name = name
    @braintree_id = braintree_id
    raise 'plan slug not recognized' unless SLUGS.include?(@slug)
  end

  SLUGS = %w(subscriber_free subscriber_paid group_free group_paid).map(&:freeze).freeze
  SUBSCRIBER_FREE = new('subscriber_free', 'Free Subscription')
  SUBSCRIBER_PAID = new('subscriber_paid', 'Monthly Subscription', 'user_monthly')
  GROUP_FREE = new('group_free', 'Group Subscription')
  GROUP_PAID = new('group_paid', 'Group Subscription', 'group_monthly')

  attr_reader :name, :slug

  def braintree_plan?
    braintree_id.present?
  end

  def price
    price_in_cents.to_f / 100
  end

  def price_in_cents
    braintree_plan? ? 5000 : 0
  end
end

The application no longer needs to have up-to-date seeds, neither its test suite to have factories in sync to be able to run.

We no longer need database migrations if a new subscription plan is added in the future. Instead, the constantized data changes alongside with the code that consumes it, making deploys simpler.

What's next?

If you found this useful, you might also enjoy don't be normal.

This article was based on the original notes in my blog.

Security update: Heartbleed

Posted 12 days back at entp hoth blog - Home

On Monday April 7th, a vulnerability in OpenSSL was disclosed as CVE-2014-0160, also known as Heartbleed. This is a serious vulnerability as OpenSSL is widely used to secure HTTPS traffic, and so it affects a large part off the internet.

All our services have been patched and secured: Tender was never vulnerable but Lighthouse was partially vulnerable through our use of Amazon Elastic Load Balancer. Our load balancer runs on a dedicated instance, which limits the data that could have been exposed. On Tuesday 8th, Amazon issued an update to their services, and we immediately updated our certificates and moved to a new load balancer.

What do I need to do?

If you are a Tender customer: nothing. Tender was never affected.

If you are a Lighthouse customer we recommend:

  • Sign out and back in
  • Change your password
  • Update all your API tokens

No malicious activity has been detected, but given the nature of the bug, and the amount of time it existed, it is better to err on the side of caution.

As usual, if you have any question, comment or concern, feel free to reach out to us at support@lighthouseapp.com or support@tenderapp.com.

Be safe.

Introducing Hound

Posted 12 days back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

We're pleased to announce Hound, a hosted service that comments on Ruby style guide violations in your GitHub pull requests.

Hound is currently free and available for public and private GitHub projects. We intend to charge in the near future to ensure Hound is sustainable, but public projects will continue to be free. Hound is also open source.

Hound example

Why code style matters

At thoughtbot, we write code that follows our open source style guide.

A consistent code style emphasizes care and team communication. It encourages other developers working in the code to keep the campground clean. It lowers the cognitive overhead for a developer reading code and lets them focus on higher-level concerns, such as the domain and the logic. It also avoids unnecessary debate during code reviews.

What we did before Hound

Historically, if we saw a style guide violation when we reviewed our teammates' code, we would comment on the line in the GitHub pull request.

That worked relatively well, but had some problems.

It was socially awkward. We tended to feel sheepish offering feedback such as:

80 character limit

Or:

Single quotes unless interpolating

It can be tedious to make many of those comments, especially for new developers on a project.

It can cause reviewers to focus on low-level style concerns instead of the primary code change.

All of those reasons can add up to not wanting to comment on every style guide violation, which can let them slip through, which erodes at the benefits of style consistency.

How Hound helps

Given those problems, a program is better than a human for reviewing code style. Hound handles checking for style violations so we humans don't have to.

Hound reviews your Ruby code when a pull request is opened or updated. If Hound finds any style violations in the modified code it will comment on the appropriate line.

Hound example

Thanks, Hound!

Open source

We're also very pleased to experiment with a model of open sourcing a hosted service from the beginning. There are so many good reasons to do this in general, and for Hound specifically:

  • It provides transparency, as users are able to understand exactly how Hound works.
  • It creates an ecosystem where third parties may extract libraries from Hound.
  • Third parties may submit pull requests to fix their own bugs, increasing the number of people who can help support Hound for all its users.
  • It places the focus value not on our super-secret-source-code but on our handling of the hosting, billing, and maintenance of that source code.
  • It provides security through the "many eyes" approach, which we believe is better than security through obscurity.

We believe Hound can be financially successful while being open source.

Ready and waiting for you

Hound has been used on over 300 GitHub projects. We've been using it internally for some time. It only takes a minute to start using it on your project.

Try Hound today.