Richard Hart

Head of Something @ Somewhere
Kent, UK

My Music
My Photos


  • While trying to setup a new Rails 5.2 app in Intellij it would continually be detected as a web project and give no way of adding the Ruby on Rails module.

    The solution is to delete the node_modules folder before creating the new project.

  • Test Working with a SOAP API with Spring Boot WS. I was getting the following error trying to create the request.

    com.sun.istack.SAXException2: unable to marshal type "com.ur-ban.GetSubscriptioninfo" as an element because it is missing an @XmlRootElement annotation

    I was originally directly using the JAXB generated classes to form my requests:

    GetSubscriptioninfo subscriptionInfo = new GetSubscriptioninfo();
    GetSubscriptioninfoResponse subscriptionInfoResponse = 
      (GetSubscriptioninfoResponse) getWebServiceTemplate()
          .marshalSendAndReceive("", subscriptionInfo);

    The correct way is to use the provided JAXB ObjectFactory:

    ObjectFactory objectFactory = new ObjectFactory();
    GetSubscriptioninfo subscriptionInfo = objectFactory.createGetSubscriptioninfo();
    GetSubscriptioninfoResponse subscriptionInfoResponse = 
      (GetSubscriptioninfoResponse) getWebServiceTemplate()
          .marshalSendAndReceive("", subscriptionInfo);

    But to prevent marshalling errors you need to wrap your object in a JAXBElement object:

    ObjectFactory objectFactory = new ObjectFactory();
    GetSubscriptioninfo subscriptionInfo = objectFactory.createGetSubscriptioninfo();
    JAXBElement jaxbGetSubscriptionInfo = objectFactory.createGetSubscriptioninfo(subscriptionInfo);
    GetSubscriptioninfoResponse subscriptionInfoResponse = 
      (GetSubscriptioninfoResponse) getWebServiceTemplate()
          .marshalSendAndReceive("", jaxbGetSubscriptionInfo);


  • One of my bad habits is constantly buying computing books. This wouldn’t be so bad if I read them, but I have amassed a huge backlog of books that will most probably never be read and which ends up being a waste of money.

    A couple of posts I read recently have led me to the decision that I should stop, or at least drastically cut down on, buying computing books. The first post talked about “learning voyerism” where you are really more interested in the idea of learning new things instead of learning the thing itself and the second talked about spending time going deeper into topics instead of boucing lightly through many different ones.

    It is very difficult to stay focused on one thing when there are so many things happening in the world of computing all the time. There are a tonne of new and exciting languages and frameworks being released all the time. And while it would be great to try them all, that can only mean that you’ll never actually become good at one of them.

    I have always been a bit of a generalist and while knowing a bit about everything isn’t a bad thing, there is a fine line between knowing a bit of everything while being proficient at some things and knowing not quite enough of everything to be unable to do anything at all.


  • Trying out chruby and ruby-install and installing Ruby 2.2.2 with ruby-install was giving be the error:

    directory not found for option '-L/usr/local/Cellar/openssl/1.0.2k/lib'

    Setting the LDFLAGS env var solved this for me:

    export LDFLAGS=-L/usr/local/opt/openssl/lib

  • To run Alacritty without spawning a new terminal window you can use Automator to create a new application wrapper.

    Create a new application document and choose Run Shell Script as the action. Then simply add the path to your built Alacritty and save the document to your Applications folder.

  • Made this mistake today while writing some code to delete data out of Redis.

    def delete_keys
      cursor = "0"
      loop do
        cursor, keys = redis.scan(cursor, count: SCAN_COUNT)
        keys.reject! { |key| keep_key?(key) }
        redis.del(keys) unless keys.empty?
        break if cursor == "0"
    def keep_key?(key)
      keep_keys.any? { |keep_key| key.include?(keep_key) }
    def keep_keys
      flattened_keys << transaction_id

    The mistake was in the final method keep_keys. Every check to see if a key should be rejected I was adding an element to the flattened_keys array over and over again, causing my deletion to slow down over time. A simple change to memoize the keep keys made the process go from never finishing to, completing in a few seconds.

    def keep_keys
      @keep_keys ||= (flattened_keys << transaction_id)

  • Copying files to a Synology NAS was painfully slow with Carbon Copy Cloner. Following the official help of ejecting the volume in Finder made all the difference. Syncs now happen as fast as they should do.

  • Text in iTerm looked a little fuzzy after moving to a non-retina 4K monitor. I discovered that setting thin strokes to always be on has made text look a lot crisper.

  • Being able to recommend products to shoppers is a vital part of any online store. The “Customers Who Bought This Item Also Bought” section can lead to a lot of extra sales if done well. The Jaccard Index is a way of measuring similarity between items. Using some custom SQL we can extract the values we need:

      product_sales AS (
        SELECT AS variant_id, SUM(quantity) as sold
          FROM spree_line_items
          JOIN spree_variants ON spree_line_items.variant_id =
          GROUP BY ),
      product_joint_frequency AS (
        SELECT v1.product_id AS product_a, v2.product_id AS product_b, COUNT(*) AS frequency
          FROM spree_line_items AS li1
          JOIN spree_line_items AS li2 ON li1.order_id = li2.order_id
          JOIN spree_variants AS v1 ON li1.variant_id =
          JOIN spree_variants AS v2 ON li2.variant_id =
          WHERE li1.variant_id != li2.variant_id
          GROUP BY product_a, product_b )
    SELECT product_a, product_b, frequency, sales1.sold AS a_sold, sales2.sold AS b_sold
      FROM product_joint_frequency
      JOIN product_sales AS sales1 ON product_joint_frequency.product_a = sales1.variant_id
      JOIN product_sales AS sales2 ON product_joint_frequency.product_b = sales2.variant_id
      ORDER BY product_a, joint_frequency DESC, product_b

    With these values we can then calculate the affinity between sold products:

    frequency / (a_sold + b_sold - frequency)



  • Since my last post about generating random email addresses in TextExpander, I’ve move from using Ruby to Applescript to do so. Here is my script which essentially does the same thing.

    set email to (do shell script "date +%s")
    set email to email & ""
    set the clipboard to email


  • A great library for adding typeahead support to your site is Twitter’s Typeahead.js. Even better is the excellent Bloodhound suggestion engine which comes with it. Sometimes though if you’re dealing with a remote suggestion engine like Elasticsearch’s completion suggester you don’t need to run remote results once again through another suggestion engine. Bypassing Bloodhound is as simple as hooking your own source function into your Typeahead definition.

      highlight: true,
      name: 'brands',
      display: 'value',
      source: function(query, syncResults, asyncResults) {
        $.get('/search?q=' + query, function(data) {


  • One of the core ideas of Rails is convention over configurations. Models go in app/models, controllers go in app/controllers and views go in app/views. The danger is that we stick to those conventions no matter what and we end up either with fat controllers, fat models or even worse a mixture of both.

    Many times we don’t take enough advantage of Ruby’s object oriented nature and the ability to extract functionality out into separate classes. Doing so can make an entire application easier to extend, understand and test. I have tried approaching this from different angles in different projects and I’ve found that the two main hurdles to getting this right are naming classes and putting them in the right place.

    I have experimented with naming such as UserAuthenticator and UserAuthenticationService, and always end up feeling uncomfortable I constantly wonder if the other name is better or if there is a better way entirely. Using agent nouns in class names is considered a code smell, but the more that I think about it the important part is picking a choice and sticking to it. I was looking at the GitLab repository and noticed that they’ve done exactly that, everything is named in a consistent manner. I think many may dislike that but it makes things extremely clear and easier for anyone contributing as to what they should name their classes and where they should put them.

  • There was a post on TechCrunch a few days ago about the big lie in startups and how you can’t run a startup without lying about a million things. When I really think about all these funded startups it upsets me, mainly because I’ve tried to bootstrap all my endeavours. That does make me sound bitter, and I am if I’m honest about it. If you start a company, get funding and fail you’re still often seen as a winner in people’s eyes where as those that bootstrap a company and fail are just seeing as losers. When did we reach a point where getting VC was the main priority after starting a business? When did we lose sight of actually trying to make money first?

  • After a rash of security updates for WordPress, I finally buckled down to move our install of WordPress off to its own server. This would be easy if we were running the blog on it’s own domain, but it was actually living under /blog on our main domain for SEO reasons. Running nginx as a reverse proxy to WordPress on a different machine was not an easy task. A lot of guides did not seem to have the information I needed so here are the steps I took to get it working.

    Add the proxy_pass definition to your nginx config:

    location /blog/ {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header X-Forwarded-Proto https;
      proxy_pass http://your-wordpress-ip-or-domain/;

    Update your WordPress settings. This is the key to getting your site to work correctly. Leave the WordPress Address as where the site is hosted, but change the Site Address to be where URLs are to be written as linking to

    Screenshot 2015-07-27 21.43.38

    I also had to add a rewrite to my .htaccess file to remove trailing slashes:

    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteRule (.+)/$$1 [R=301,L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]

    Be warned that the permalinks section will suggest a .htaccess file which has /blog/ as the RewriteBase, but this just sends things into a redirect loop. Leave it as the standard root setting.

    Make sure you also check that the canonical tags generated by your theme are correct. You want to be sure that any references on the WordPress Address URL canonicalise to Site Address URLs.

  • Facebook’s Four Business Design Principles is an excellent reference that should be at the core of every business tool.

    Help people learn and grow

    Balance efficiency and effectiveness

    Bring clarity to complexity

    Be accurate and predictable

    The majority of my time these days is spent writing tools for business as opposed to consumer facing sites and trying to find the balance between ease of use and providing all the elements necessary to complete a task can be very difficult at times. I had not heard of the Goldilocks Principal before but it perfectly summarises this fine balancing act.

    With a complex piece of UI, if you don’t simplify it enough, people can’t figure out how to use it. But if you swing too far in the other direction and over-simplify it, you risk dismantling the very value that people are looking to access through the tool.

    When immersed in a tool it’s easy to become blind to the experience of actually using it. A good example are the drop down menus on a site I’ve been working on these past few years. Even though we would all use them day to day they were never really given a second thought. It was only after looking into how they were actually performing that it was apparent that they were actually really awful to use. Our own familiarity had caused a massive disconnect between how effective they were to use.