AB Testing, from scratch

If you work in a diligent web development business you probably know what an A/B test is. However, its fascinating statistical theory is usually left behind. Understanding the basics can help you avoid common pitfalls, better design your experiments, and ultimately do a better job in improving the effectiveness of your website.

Please hold tight, and enjoy a pleasant statistical journey with the help of R and some maths. You will not be disappointed.

Read the full article

25 Nov 2015

Bringing Ruby fetch to the Javascript world

If you are a Rubyist you are probably comfortable using the #fetch method on a day-to-day basis but when you are developing in Javascript this sweetness is not immediately available. This is why I wrote underscorejs-fetch.

Read the full article

20 Feb 2015

Refactoring a complex front-end calendar

Frontend components are hard to implement and more often than not the code reflects this complexity. In this blog post I will show you how I refactored the code of a complex frontend calendar sharing some of the findings that led to a cleaner implementation.

Read the full article

25 Nov 2014

Using machine learning to rank search results (part 1)

A large catalog of products can be daunting for users. Providing a very fine grained filtering of search results can be counter-productive: it leads them from information overload to lack of choice.

On e-commerce sites, this results in poor conversion—users leaving the site without checking out.

The key is obviously to provide relevance and choice, which is much more complicated than it sounds, as different users may have very different tastes.

This describes how I explored a machine learning, neural networks based solution to relevance ranking.

We’ll demonstrate that an ANN (artificial neural networks) based approach can provide better ranking than our historical ranking heuristics, and still provide good performance.

Read the complete article on my blog.

Credits: Thanks to Alfredo Motta and Andy Shipman for their helpful review of this article.

photo of Julien Letessier

Software Engineer
20 Oct 2014

A journey through a Web App optimization session

Fast web apps are beautiful to use and are one of the key requirements for a successful user experience. In this blog post I will show you how to analyze the performance of your web app and take actions to speed it up.

Read the full article

29 Sep 2014

RESTful -and- fast: Representational State Notification

Adding lightweight state change notifications to the REST architecture style can alleviate some of its performance limitations, without violating its principles. It also obviates the temptation to revert from a RESTful, domain- centric resource oriented architecture to an RPC-style, function-centric microservice architecture.

If you care mostly about the solution, feel free to skip to the section about Routemaster. The beginning of the article presents the concepts and rationale.

Read the full article

20 Sep 2014

Decoupling JavaScript applications using the Publish/Subscribe pattern

Design patterns are a great tool for developers, providing us with generalised and reusable solutions to common problems in software development. In this post we’ll see one of the more valuable patterns for modern applications, the Publish/Subscribe pattern and how to use it in JavaScript applications.

Read the full article

15 Sep 2014

Writing Specs without Rails for Legacy apps

The why and how of writing specs without requiring Rails for legacy apps in order to move towards a hexagonal style architecture.

Read the full article

12 Sep 2014

Compute property recommendations - A collaborative filtering approach

In this blog post we show how to build a simple property recommendation engine. What are the possible design choices, how to implement them in practice, and how to validate the performance of your system.

Read the full article

08 Aug 2014

Rails with PostgreSQL on Docker using Fig

This post describes the steps to get an existing Rails app running on Docker using Fig. The focus is development and test, and getting comfortable using Docker.

Read the full article

06 Aug 2014

Deploy a Rails and PostgreSQL app to Dokku

In an age of SOA and microservices, having a platform to quickly deploy and manage you applications on is priceless. This post details getting a Rails application using PostgreSQL running on Dokku (a docker based mini-Heroku).

Read the full article

06 Jul 2014

Breaking down a Rails 2 monolith using plugins

Breaking down a large Rails 2 application can be a daunting task. Rails plugins can be used to take the first step, by gathering all business logic and tests in one folder.

Read the full article

24 Jun 2014

Go in 42 lines of Ruby

Go’s Goroutines are like sugar. They give me a rush, and my IO-bound work as well!

But for a one-off script, my Go’s not fluent enough, so why not bring some of it to Ruby?

Read on for a no-frills approach to go { do_stuff }.

Read the full article

13 Jun 2014

Page objects, or how to better test by wrapping HTML with code

Using page objects can help greatly with testing DOM or portions of it.

Read the full article

22 May 2014

Benchmark RubyGem load times

How can you benchmark the time that your gems take to load?

Read the full article

08 May 2014

Nested Resources with Backbone

I want to share my solution to a topic that seems wide spread throughout the Internet without using any third party plugin to achieve it on Backbone, and for that I will use a 3 level nested resource as an example, giving you the necessary insight to make you fearless in this subject.

Read the full article

22 Apr 2014

Unleash your AJAX requests with CORS

Cross-origin resource sharing is a mechanism that allows your AJAX requests to reach new territories. Let’s refresh our knowledge on AJAX requests, their limits and how CORS helps to circumvent them.

Read the full article

17 Apr 2014

Document and comment code? Or don't?

The stance on documentation in the Ruby community seems to oscillate between “RDoc the hell out of it” or “nah, the code (or the test suite) is the documentation”.

We think both are untrue, and have a pragmatic middle ground: “documentation” per se exists mostly under the skullcaps of team members, but some things do need minimal documentation. Read on for more.

Read the full article

07 Apr 2014

Regaining lost memories

A few things you can try to keep your Rails app’s memory usage in check.

Read the full article

01 Apr 2014

Timing Rack Middlewares with metaprogramming, recursive monkey-patching, and a sprinkle of statistics

Analysing performance of your Rails or Sinatra app is easy enough with New Relic, but figuring out whether the soft outer shell of your stack is under-performing is more of a challenge. We’ve written rack-timer to figure things out.

Read the full article

27 Mar 2014

Quick tip. Is my process alive? (in Ruby)

How do you figure whether a process is currently running, in a reasonably portable manner? I keep forgetting how to do this for some reason, and needed it for my tinkering with Babushka so might as well write it down.

Read the full article

24 Mar 2014

Ruby installations on steroids

If you are using Ruby, chances are you’re using Rbenv to manage Ruby installations. This post concerns some plugins and tips to make Rbenv even more awesome.

Read the full article

17 Mar 2014

Continuous Deployment

Do you trust your software and processes? Prove it and do continuous deployment

Read the full article

12 Mar 2014

Homogenizing your codebase

Having all members of the team write code with a similar style is important, for the sake of readability. Here’s how we try to achieve this.

Read the full article

04 Feb 2014

Efficient cross-process locking in Ruby

In this blog post we cover how we currently handle sensible transactions between several processes in a thread safe way.

Read the full article

28 Jan 2014

Trailer, a faster and easier way to deal with pull requests

Introducing Trailer from HouseTrip, a simple menu bar app that helps you manage your GitHub pull requests. It’s one feature we felt was lacking from our workflow!

Read the full article

22 Jan 2014

Using BackboneJS in non-single-page applications

During a recent redesign of several essential pages, we decided to create a new layout and adopt BackboneJS as our front-end framework. This post describes our approach to introducing a JavaScript framework into a large Rails application.

Read the full article

20 Jan 2014

How to create your own Singleton from Scratch

Ruby provides you with lots of modules ready to use, one of them is the Singleton Module. Although it’s a good thing to know what’s under the hood and create your own from scratch.

Read the full article

16 Jan 2014

Session storage and security in Rails

We’ll explore how Rails handles and stores the session information, what security implications it has, and what alternatives we can use.

Read the full article

14 Jan 2014

Dragonfly backed by ActiveRecord

If your app’s dynamic assets (user uploaded images for instance) weigh up to a few gigabytes, it can make sense to store them in the app’s database instead of another service (e.g. Amazon’s S3): your stack has one less dependency to care about, and backups get more complicated.

If you’re using the excellent dragonfly to manage and serve such assets, we’ve just released dragonfly-activerecord which lets you store assets to your app’s relational database.

It chunks and compresses files, is compatible with a variety of Rubies and databases, and is a drop-in replacements for Dragonfly’s default stores. It also plays nicely with Rack::Cache and/or a CDN for better performance.

13 Jan 2014

Rebund for 4x faster Travis builds

Running bundle install to get all gems ready is often the longest part of a build. Any Rails application will depend on tens of gems; and any gem, besides dependencies, may have a fairly large build matrix.

Rebund can easily cut your build times by 75%, saving you time and saving the good folks at Travis CI some money.

Read the full article

06 Jan 2014

Good software comes with a good README

Having a good README is crucial to see a software project get adopted and well used.

Starting with a good README also helps you focus on your API or UI first.

The TL,DR:

  • be concise and a bit sales-y
  • hand-hold your users into installation and initial usage, and around traps
  • make it a portal for further information

Read on for a few hopefully useful hints.

Read the full article

29 Nov 2013

Legacy won't be the end of us

By this I mean…having a lot of old code in your codebase shouldn’t stop you from becoming a good software engineer, as long as you follow good practices and are up to date with the latest trends. You also need a strong will, but nothing is unachievable.

Read the full article

26 Nov 2013

Using data tiering to squeeze scale out of SQL

As traffic grows, some of the data structures our application has to manipulate gets contended. Ours is an unusual, but effective solution: segregate data into read-mostly and write-mostly.

Read on for the nitty gritty.

Read the full article

15 Nov 2013

Work in multiple branches with Git Workdir

Ever wanted to have your checkout in multiple states at one time without having to maintain several .git folders? This post described how a script from git-contrib can help you achieve parallel git nirvana.

Read the full article

08 Nov 2013

Scala - first impressions of a Ruby developer

I am always curious about languages I don’t know, even more so when a language is considered ‘trendy’. But I am also careful and trendy doesn’t mean good. So to make my own opinion, I decided to give Scala a try.

Read the full article

29 Oct 2013

Introducing git-whistles

A short interview with (Developer) David Silva. The topic of discussion is git-whistles, a gem we use extensively here at HouseTrip that helps with our git based workflow.

Read the full article

11 Oct 2013

New Geo Polygon Tools

A short interview featuring (Developer) Dawid and (Performance Marketing Specialist) Carl. The topic of discussion is recently launched tool that helps us easily manage new destinations for properties on HouseTrip.

Read the full article

07 Oct 2013

Faster Git workflows

Yes, you can Git faster. This post covers how a mixture of environment variables and aliases can increase the speed of your daily Git workflows.

Read the full article

01 Oct 2013

Monitoring backend services, a tale of delays and dogs

We wanted to share how we evolved our asynchronous job processing over the past year. The TL,DR of our findings are:

  • Using DelayedJob for queueing/running asynchronous tasks scales well, in terms of throughput, variety of jobs, and cost of maintenance.
  • This does require backing it with Mongo (for high throughput) and keeping it agnostic to the type of jobs it’s running (for low maintenance).
  • We found it more practical to manage a limited number of queues based on urgency bands, rather thand trying to prioritise individual jobs based on (perceived) importance.
  • Good monitoring is imperative, but trivial to achieve with statsd and a good frontend/alerter like Datadog.

Read the full article

12 Sep 2013

Maintaining Session Data from Ruby 1.8.x in 1.9.x

tl;dr - You cannot just update to Ruby 1.9.x without losing your session data. Unless you serialize in a portable format (e.g. JSON) and rebuild any complex objects being stored.

Read the full article

12 Sep 2013

Testing Active Resource Models

Active Resource can be a great way to move models from an application into separate services. This post covers some strategies for testing active resource services.

Read the full article

21 Aug 2013

Maintaining Code Quality at Housetrip

I joined HouseTrip in August, 2012 and since then I have not seen any code deployed to production without a peer review (barring a few exceptional hot-fixes). I found out that this was not always the case, in fact, (like many early stage startups) code used to go live without any reviews and we sometimes ended up with careless design and accrued technical debt.

Read the full article

02 Jul 2013

Configuring Pow with NGINX and SSL on OSX

This is a step by step guide on how to setup your local development environment to serve a Rails (or any Rack) app with Pow and NGINX over HTTPS. To begin I’m going to assume you’re using OSX (probably Mountain Lion), HomeBrew and rbenv. For other setups ymmv.

Read the full article

21 Jun 2013

Runtime extends with Ruby

Ruby is a dynamic language which supports many ways to organise logic. We can use class inheritance or/and compose our classes by including selected modules (mixins). We can define or un-define methods on the fly. We can even use methods that are not really defined (using method_missing). Using characters in an RPG game as an example, this code walk-through explains a design pattern for extending objects with new methods at run-time.

Read the full article

06 Jun 2013

Rspec 1.3.x cookie issue with Ruby 1.9.3 & Rails 2.3.x

At HouseTrip we use RSpec and cucumber for all our tests. While upgrading our app to Ruby 1.9.3 we hit a strange issue testing cookies in our controller specs.

In RSpec, you can fetch cookie values by using the cookies hash as cookies[:cookie_name] just like in the Rails controller, views and helpers. However, all our cookie related tests failed because the value of cookie_name was never being set. We found that we could still access the cookies using response.template.cookies meaning the cookies were being set correctly, but there was something not right with the tests.

Read the full article

22 May 2013

DCI with Ruby & Rails -- HouseTrip at LRUG

Data Context Interaction is a recently invented programming paradigm aiming to separate behaviour from your data model. By extracting interactions into roles, they can be played by objects in various contexts.

I recently gave a talk about DCI at the London Ruby User Group (LRUG). The presentation gave a brief introduction to DCI, proposed ways to implement role injection, and discussed how DCI could be used to supplement the Rails MVC paradigm.

20 May 2013

Git Stashing

Moving between different branches during my work I have discovered how useful git stash can be. The more I use it and the more tricks I read, the more confident I feel with it. The stash is useful when you need to save your changes to a temporary place, move onto something else and then get back to your changes afterwards.

Read the full article

13 May 2013

fuzzily and blurrily - two fast fuzzy-text search/match gems

Users make spelling mistakes… espacially when typing the name of an exotic destination.

Show me properties of **Marakech** !

  > Here are some properties in **Marrakesh**, Morroco.
  > Did you mean **Martanesh**, Albania, **Marakkanam**, India, or **Marasheshty**, Romania?

fuzzily and blurrily both find misspelled, prefix, or partial needles in a haystack of strings, quickly.

With a database of 10 million entries, blurrily can find fuzzy matches for any input string within 75ms on typical hardware. On less pathological datasets, you can easily expect searches to take no more than a few milliseconds, typically faster than caching!

Both gems are tested with various Ruby VMs and versions of Rails, and here at HouseTrip we’re actually using blurrily in production.

Fuzzily

Fuzzily is Blurrily’s older brother. It is easier to integrate into an typical Rails application and lets you make any model’s attributes searchable:

class MyStuff < ActiveRecord::Base
    # assuming my_stuffs has a 'name' attribute
    fuzzily_searchable :name
  end

  MyStuff.find_by_fuzzy_name('Some Name', :limit => 10)
  #=> records

Installing and using it can be done in minutes with a typical Rails application.

Blurrily

Fuzzily’s younger sibling is slightly harder to integrate, but it’s crazy fast (backed by a C extension) and scales very well. You can use it as a client/server like so:

$ blurrily &
  $ irb -rubygems -rblurrily/client
  > client = Blurrily::Client.new
  > client.put('London', 1337)
  > client.find('lonndon')
  #=> [1337]

Or directly:

$ irb -rubygems -rblurrily/map
  > map =
  > client.put('London', 1337)
  > client.find('lonndon')
  #=> [1337]

If you have a similar problem and feel ElasticSearch or anything Lucene backed is overkill, why not give them a go!

photo of Julien

Developer
06 May 2013

mrd - MySQL in a RAMDisk for speedier tests

We try to live by the “red, green, refactor” mantra at HouseTrip. As a consequence we have good test coverage, but our test suite is getting larger. This is just one of the tricks that help us run our tests faster.

Many of our tests tend to use live ActiveRecord objects, which means the database can be a speed bottleneck. Even with good SSDs, the heavy, synchronous I/O performed when creating and modifying records is a grind.

A common idea is to make your test database’s storage live in memory instead of on-disk, and that’s exactly what mrd sets up for you.

Yes, mrd is pronounced like the french swear word, (sorry if you find that in poor taste). The rationale here, is that you might end up saying that word a lot (or the equivalent in your own language) after manually setting up MySQL-in-a-RAMdisk a couple of times.

Fortunately, setting up mrd is trivial; just install like so:

$ gem install mrd
  Successfully installed mrd-0.0.3
  1 gem installed

and run:

$ mrd
  ==>
  Created Ramdisk at /dev/disk4
  Formatted Ramdisk at /dev/disk4
  Mounted Ramdisk at /Volumes/MySQLRAMDisk
  Starting MySQL server
  MySQL is now running.
  Configure you client to use the root user, no password, and the socket at '/Volumes/MySQLRAMDisk/mysql.sock'.
  Just close this terminal or press ^C when you no longer need it.

Then, if using Rails, point your database.yml to this new temporary SQL server:

test:
    ...
    socket: /Volumes/MySQLRAMDisk/mysql.sock

Don’t forget to setup your test database:

$ bundle exec rake db:create:all db:test:prepare

Voila! Slightly faster tests.

A couple of caveats to finish:

  • mrd only supports MacOS, but you’re very welcome to fork & extend for other platforms!
  • This is a hastily hacked together script. I’ve been using it for six months without problems though.
photo of Julien

Developer
29 Apr 2013

HT - one command to rule them all

DRY doesn’t just apply as a best practice for software development. At HouseTrip, we’re always looking for better ways to automate things. Everything we do repeatedly, should be a candidate for optimisation. From simply connecting to servers, to pulling down stats on our production job queues.

As a team we have amassed a collection of shortcuts, scripts, and rake tasks to make our lives just a little bit easier. In an effort share amongst everyone, I have decided to formalise them all in a new ht command.

37signals Sub

The ht command uses sub, a command line framework from 37signals. It’s an awesome starting point for building commands just like this, with autocompletion, help, bash/zsh support and aliases all built in.

Helpers and configuration!

Sub has some great conventions, but to allow us to direct commands at any one of our (many) staging and production servers, I forked sub and added some helpers and configuration options. At HouseTrip, staging servers can be temporary things, so its important we can easily change where to direct commands.

Server connection information lies in a simple yml file for each Rails environment we have. So we can issue a single command like this;

ht console staging100

and be running a Rails console (on the remote staging100 environment) in no time at all. In the future I’ll try to create a pull-request for this (to sub). Sticking with some conventions, i’ve written all our ht commands in Ruby and created a number of helper classes for logging output (even talking output with the built-in OSX ‘say’ command).

Command Ideas

To give you some ideas, here’s a short list of some of the commands we are building (or have already built);

  • ht-ssh (env) - connect to any server
  • ht-console (env) - ssh and Rails console onto server
  • ht-dump (db-name) - grab a fresh (anonymised) database dump and import it to your local env
  • ht-cache-clear (env) - clear the Rails.cache on a server
  • ht-be-admin (env) (username) - convert an existing user to an admin
  • ht-jobs (env) - get some basic stats on the job queues
  • ht-bump-job (env) (id) - bump priority of a remote job
  • ht-booking (env) - show stats on the last booking made
  • ht-gif (keyword) - fetch an animated gif into your paste buffer
  • ht-git-visual (time-ago) (repo) - visualise git repository activity since (time ago) with Gource
  • ht-add-server (config) - add new server details to the ht config file
  • ht-mugshot (keyword) - grab a photo from our team intranet page
  • ht-starter - kick off a setup script that installs and configures your laptop for HouseTrip development
photo of Matt

Developer
20 Apr 2013

Don't want MySQL filesort? Here's how to kill it dead!

When using EXPLAIN to find the finer details of what is going on under the hood, you will surely come across this,

Using where; Using temporary; Using filesort

or some combination like that. The important things to notice here are temporary and filesort. Fixing temporary requires carefully defining indices, more on that subject can be found in the MySQL docs.

Fixing the filesort, (especially when your SQL is abstracted by something like ActiveRecord) can be a little more tricky. The problem comes from using ` … :group => “[column]” ` in our scope, for example.

Booking.all(
    :select => "count(1) as bookings_per_day, date(created_at) as booking_date",
    :conditions => [
      "user_id = ?
      and status = 'accepted'
      and pending = 0
      and created_at between ? and ?",
      @user.id,
      extract_date(dates.first.beginning_of_week),
      extract_date(dates.last)
    ],
    :group => "booking_date")

The SQL query derived from this code results in a ‘filesort’ opertation, something we want to avoid. MySQL docs state:

By default, MySQL sorts all GROUP BY col1, col2, … queries as if you specified ORDER BY col1, col2, … in the query as well. If you include an ORDER BY clause explicitly that contains the same column list, MySQL optimizes it away without any speed penalty, although the sorting still occurs. If a query includes GROUP BY but you want to avoid the overhead of sorting the result, you can suppress sorting by specifying ORDER BY NULL.

Bingo!

INSERT INTO foo
  SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;

So let’s go back to the code and add that in.

Booking.all(
    :select => "count(1) as bookings_per_day, date(created_at) as booking_date",
    :conditions => [
      .. etc ..
    ],
    :group => "booking_date",
    :order => "null")

Note that it isn’t :order => nil. This results in the order not being included in the result SQL at all.

The EXPLAIN now gives us Using where; Using temporary. Chances are, the order implied by the :group is what you want anyway. Of course, if you were sorting by a column explicitly you would care about the order, in which case you would be stating this in the query. It’s almost as if ActiveRecord should know to add this if there is no :order specified when using :group.

For more detail on exactly what MySQL is doing when filesorting, take a look at this detailed article, How MySQL executes ORDER BY

photo of Marcus

Lead Developer
19 Apr 2013

Good looking shadowy CSS3 tabs

I’m going to show you guys how to create some nice looking tabs using CSS3 (sorry old IE guys!) Basically I didn’t find a good solution online for good looking tabs that were easy to do and that also looked nice, so I ended up by creating our own Housetrip version.

Read the full article

15 Jun 2012

Announcing, the HouseTrip Developers Blog

Congratulations! You have found your way to the new HouseTrip Developers Blog! Through a series of upcoming posts we hope to entertain and delight you with tales of the technical challenges we’ve overcome and some of our ideas for the future. Stay tuned while we rack our brains for some topics to post!

About HouseTrip

HouseTrip was founded in 2009 by Arnaud Bertrand and Junjun Chen. Arnaud and Junjun met whilst studying hospitality management at the acclaimed Ecole Hôtelière de Lausanne in Switzerland.

The HouseTrip concept was born as a result of a mutual love of staying in holiday rentals while travelling. The trigger event occurred whilst trying to book a rental for a weekend in Scotland, with a booking process that was so complicated that they decided to dedicate themselves to making it simpler. Their thinking was; “since rentals are better value and more ‘authentic’ than hotels, if it’s easier and safer to book rentals, more people will choose them over hotels.” Given HouseTrip’s early success, this has so far held true!

photo of Matt

Developer
18 May 2012