How to retry SSH, API, and external connections in Rails 4

This is pretty much a no-brainer, but in case you’re in doubt, this is an easy way to retry external connections. This way you don’t automatically halt the application at the slightest network issues.

I’m using Peakium as an example of API connection, but you can do this with pretty much anything as long as you rescue from the right exception type (should only be in case there is connectivity issue).

# models/concerns/peakium_retry.rb
module PeakiumRetry
  def peakium_retry(&block)
    retries = 1
    begin
      block.call
    rescue Peakium::APIConnectionError => e
      raise e if retries == 0
      retries -= 1
      sleep 0.5
      retry
    end
  end
end

This will retry the connection one time if failing (waiting half a second between tries), and throw the exception if it fails again.

You will just do the call like this:

events = peakium_retry do
  Peakium::Event.all(params, peakium_access_token).data
end

Straight forward, and easy.

Rails: How to fix issue with unique number under scope that doesn’t count correctly with find_or_create_by

The bug fixing was very frustrating. Take a look at the following example:

class Model < ActiveRecord::Base
...
  # Set a unique scoped number
  validate do
    errors.add(:scoped_unique, "is already taken") if parent_parent_model.parent_model.models(true).where(scoped_unique: scoped_unique).where.not(id: id).present?
  end
  before_validation on: :create do
    self.scoped_unique = (parent_parent_model.parent_model.models(true).collect { | model | model.scoped_unique }.max.to_i || 0) + 1 if self.scoped_unique.nil?
  end
...
end

This works just fine when you are creating a new model like this:

parent_model.models.create(...)

However using find_or_create_by it adds unexpectedly additional parameters to the scope the model itself with the parent_model (thus not restricting itself to parent_parent_model only)!

parent_model.models.create_with(...).find_or_create_by(...)

Turns out you have to unscope the whole query:

class Model < ActiveRecord::Base
...
  # Set a unique scoped number
  validate do
    Model.unscoped do
      errors.add(:scoped_unique, "is already taken") if parent_parent_model.parent_model.models(true).where(scoped_unique: scoped_unique).where.not(id: id).present?
    end
  end
  before_validation on: :create do
    Model.unscoped do
      self.scoped_unique = (parent_parent_model.parent_model.models(true).collect { | model | model.scoped_unique }.max.to_i || 0) + 1 if self.scoped_unique.nil?
    end
  end
...
end

Rails: button_to with [data-confirm] tries to confirm tries and nothing happens

If you are using jquery-ujs and happens to get two confirm dialogs when using [data-confirm] with a button, all you have to do is put the data confirm attribute in a form attribute:

Before:

<%= button_to registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete do %>
    Cancel my account
<% end %>

After

<%= button_to registration_path(resource_name), form: { data: { confirm: "Are you sure?" } }, method: :delete do %>
    Cancel my account
<% end %>

Rails: Unique constraint and acts_as_list

Here’s a quick tip to fix issues with unique constraints and acts_as_list gem. The issue stems from the moving model’s position not being set to NULL during the move.

Rails 4: How to set parent model on both left and right side in a has_many :trough relationship, models being created with nested attributes

Let’s say you have a many-to-many setup, with same parent for both left and right side. You might want to create an account, with a user and a project in one go.

Fix nokogiri install issue on Mac OS X 10.9

When installing nokogiri 1.6.1 on my RubyStack installation with Mac OS X Mavericks I got the following error.

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

Running ‘configure’ for libxml2 2.8.0… ERROR, review ‘tmp//ports/libxml2/2.8.0/configure.log’ to see what happened.

The configure.log said that the gcc/make could not be found. While figuring it out I found a lot of issues, and the information for fixing them was all deprecated.

The following steps solved my issues completely:

# sudo xcode-select -switch /Library/Developer/CommandLineTools
# gem uninstall nokogiri libxml-ruby
# gem update --system
# gem install nokogiri

Gem update is unnecessary, but good to have just in case. Hope this helps.

Install phalcon with MAMP

This is instructions on how to compile and install the phalcon extension on Mac OS X (Lion), along with command-line tools. Everything will be done through the terminal, except installation of Xcode and the command-line tools.

How to secure your MAMP files with Dropbox

In this post I will describe the setup I use with Dropbox to secure all my important MAMP data.

Background: I like to have my MAMP and development environment backed up in case of getting a new computer, my hard disk crash, or anything happens to the data. I can get right back to where I left. It is not a good idea to just put the whole MAMP directory on Dropbox, because you would not want to back up temporary files. I do want to back up binaries, MAMP itself, and any files I need to actually start MAMP on a different computer.

Elegant flexible (automatic) coloring in Javascript

In this piece I will show you how you can calculate esthetic colors using Javascript. In this particular case the result will be a glossy button, but this technique can be used for anything.

Background: At cSupport we have a very different idea of how to work with design. While most of our competitors use fixed templates, or have a huge palette where you need to decide every single color, we believe that it should be much more straight forward, and elegant. Give us one color, and we will calculate everything else needed for delivering a gorgeous layout. We have used this setup for more than 2 years now, and I think it is time for us to reveal how!

Asynchronous (non-blocking) lazy loading of external javascript

Here’s a simple solution to the issue of having external javascript components make your page look like it loads slow. Of course, if you need the javascript “as soon as possible” (meaning that you wish the javascript to run at the same time as your page is rendered), then you should not do this. Instead just go for an asynchronous load.