3565 cards

Minimal JavaScript function to detect version of Internet Explorer or Edge

If possible your code should detect features, not browsers. But sometimes you just need to sniff the browser. And when you do, you're probably fighting a Microsoft product.

The following function returns a Number like 10, 11, 12, 13 for Internet Explorer or Edge (anything above 11 is Edge). It returns undefined for any other browser.

function ieVersion(uaString) {
uaString = uaString || navigator.userAgent;
var match = /...


How to make changes to a Ruby gem (as a Rails developer)

At makandra, we've built a few gems over the years. Some of these are quite popular: spreewald (475k downloads), active_type (330k downloads), and geordi (210k downloads) for example (numbers from 2018).

Developing a Ruby gem is different from developing Rails applications, with the biggest difference: there is no Rails. This means:

  • no defined structure (neither for code nor directories)
  • no autoloading of classes, i.e. you need to require all files yourself
  • no [active_support](https://api.rubyonrails.org/classes/ActiveSupport.ht…

HTML forms with multiple submit buttons

Most forms have a single submit button that will save the record when pressed.

Sometimes a form needs additional submit buttons like "accept" or "reject". Such buttons usually attempt a state transition while updating the record.

To process a form with multiple buttons, your server-side code will need to know which button was pressed. To do so you can give each submit button a different [formaction] attribute. This will override the …

SSH: X-Forwarding

If you need to run a program on a remote machine (e.g. to your office PC) with a graphical UI (and you trust the remote machine), you can use SSH X-Forwarding. I sometimes use this to connect to a virtual machine installed on my work PC from my home office.

Forwarding X over SSH

To use X forwarding, when connecting to the remote machine, and add -X to the ssh call. Now, when you start a program with a UI (e.g. virtualbox) in that SSH session, a window will open on your local machine. It will not be particularly …


Project management best practices: Project team responsibilities

In a project team for a bigger project people have several roles:

  • Developer: at makandra
  • Project lead: at makandra
  • Project manager (PM): at makandra, external, or with the customer. In a smaller project this person is also the project lead.
  • Product owner (PO): with the customer


  • Development
  • Take responsibility for their stories. This includes always gathering all necessary information from the project lead or the PM, communicate blockers, make sure stories are merged, deployed etc.
  • Tell the project lead, if you'r…

Best practices: Large data migrations from legacy systems

Migrating data from a legacy into a new system can be a surprisingly large undertaking. We have done this a few times. While there are significant differences from project to project, we do have a list of general suggestions.

Before you start, talk to someone who has done it before, and read the following hints:

Understand the old system

Before any technical considerations, you need to understand the old system as best as possible. If feasible, do not only look at its API, or database, or frontend, but let a user of the old system sho…


PostgreSQL and its way of sorting strings

PostgreSQL uses the C library's locale facilities for sorting strings:

  • First, all the letters are compared, ignoring spaces and punctuation.
  • Then, spaces and punctuation are compared to break ties.
  • It sorts upper and lower case letters together. So the order will be something like a A b B c C


Ruby PostgreSQL
IMAGE3.jpg image2.jpg
image.jpg image3.jpg
image2.jpg IMAGE3.jpg
image3.jpg image.jpg

[PostgreSQL-FAQ: Why_do_my_strings_sort_incorrectly](https://wiki.postgresql.org/wiki…

Linked contentRepeats

AppArmor in Linux

This note is a reminder that there is something called AppArmor that could cause weird errors ("File not found", "Can't open file or directory", …) after configuration changes, e.g. when changing MySQL's data directory.

Remember to have a look at AppArmor's daemon configuration (usually at /etc/apparmor.d/) if you change daemon configuration and run into errors such as the one above.


Trigger native mouse events with Javascript

The attached Coffeescript helper will let you create mouse events:

$element = $('div')

The dispatched events are real DOM events, which will trigger both native and jQuery handlers.
jQuery's .trigger is simpler, but will only trigger event handlers that were bound by jQuery's .on.

Real user actions t…

How to fix: Corrupt special characters in ZIPs on Linux

When you receive a ZIP file from a Windows user, umlauts and other non-latin1 characters in filenames may look corrupt, and probably will be corrupt when extracting the ZIP file.

The reason is encoding: Such archives are probably using Codepage 850. I am serious, 1987 is calling.

Fortunately, the unzip command can handle such files like so:

unzip -O CP850 file.zip

Interestingly enough, Rubyzip also compresses files that way. Probably so files look alright to Windows users.

Chrome bug: Wrong stacking order when transitioning composited elements

Google Chrome has a subtle rendering bug that hits me once in a while. It usually occurs in sliders with HTML content.

The issue

When a slider contains a composited[1] element, the element will overlap any other element when sliding, being rendered as frontmost element. After the slider has settled, stacking order jumps back to normal.

It seems like Chrome is doing its compositing wrong. This doesn't happen in Firefox.

The cause

The issue only occurs if:

  • two elements A and B are nested inside an element C
  • A overlaps B (part…

Trigger a link's click action with Javascript


Use the click method from the raw DOM element (not the jQuery object):

$link = $('a:first');

Mind the [0].

Long story

Triggering a link's click action seems easy on first sight:

$link = $('a:first');

Unfortunately that only triggers click event handlers that were registered through jQuery. It will not make a link navigate to its href.

To make a link navigate to its href you need to say:

$link = $('a:first');
location.href = $link....

Pitfall: ActiveRecord callbacks: Method call with multiple conditions

In the following example the method update_offices_people_count won't be called when office_id changes, because it gets overwritten by the second line:

after_save :update_offices_people_count, :if => :office_id_changed? # is overwritten …
after_save :update_offices_people_count, :if => :trashed_changed? # … by this line

Instead write:

after_save :update_offices_people_count, :if => :office_people_count_needs_update?


def office_people_count_needs_update?
  office_id_changed? || trashed_changed?

Or, move t…

Linked contentRepeats

Verifying doubles in RSpec 3

RSpec 3 has verifying doubles. This breed of mock objects check that any methods being stubbed are present on an instance of a given class. They also check methods aren't called with the wrong number of arguments.

This dual approach allows you to move very quickly and test components in isolation, while
giving you confidence that your doubles are not a complete fiction.

You should always prefer using a verifying double to using an old-…

Haml: Generating a unique selector for an element

Having a unique selector for an element is useful to later select it from JavaScript or to update a fragment with an Unpoly.

Haml lets you use square brackets ([]) to generate a unique class name and ID from a given Ruby object. Haml will infer a class attribute from the given object's Ruby class. It will also infer an id attribute from the given object's Ruby class and #id method.

This is especially useful with ActiveRecord instances, which have a persisted #id and will hence **generate the same selector o…

Haml: Prefixing a group of attributes

Haml lets you prefix a group of attributes by wrapping them in a hash. This is only possible with the {} attribute syntax, not with the () attribute syntax.

Example: HTML5 data attributes

HTML5 allows you to use arbitrary attributes like data-method and data-confirm. You can prefix a group of data- attributes like this:

%a{href: '/path', data: { method: 'delete', confirm: 'Really delete?' }} Label

This compiles to:

<a data-confirm='Really delete?' data-method='delete' href='/path'>Label</a>


3 ways to run Spring (the Rails app preloader) and how to disable it

spring ...

The most obvious way to use spring is to call it explicitly:

spring rails console
spring rake db:migrate


Binstubs are wrapper scripts around executables. In Rails they live inside bin/. If you run spring binstub --all, your binstubs will be using Spring.

bin/rails console
bin/rake db:migrate

bundle exec rails ...

Bundle exec is inconsistent when it comes to spring. Some commands will use it, some won't.

bundle exec rails console # starts Spring…


ActiveRecord: When aggregating nested children, always exclude children marked for destruction

When your model is using a callback like before_save or before_validation to calculate an aggregated value from its children, it needs to skip those children that are #marked_for_destruction?. Otherwise you will include children that have been ticked for deletion in a nested form.

Wrong way

class Invoice
  has_many :invoice_items
  accepts_nested_attributes_for :invoice_items, :allow_destroy => true # the critical code 1/2
  before_save :calculate_and_store_amount                              # the critical code 2/...
This website uses cookies to improve usability and analyze traffic.
Accept or learn more