3549 cards
View
Repeats

Collect all values for a given column in an ActiveRecord scope

The Edge Rider gem allows you to collect an array of values for one field of your ActiveRecord elements:

>> User.active.collect_column(:id)
=> [1, 5, 23, 42]

It also comes with a :distinct option in case you are only interested in unique values:

>> Article.collect_column(:state, distinct: true)
=> ['draft', 'published']

In modern Railses (since 3.2) you can also use ActiveRecord's pluck met…

Linked contentRepeats

Nested ActiveRecord transaction pitfalls

When working with custom transactions you may encounter unexpected behaviour if you try to roll back your changes.

tl;dr

Not all databases support nested transactions. Therefore, Rails will sometimes silently ignore a nested transaction and simply reuse the other transaction. However, a ActiveRecord::Rollback within the nested transaction will be caught by the block of the nested transaction, but will be ignored by the outer transaction, and not cause a roll back!
To avoid this unexpected behaviour, you have to explicitly tell rai…

Repeats

Hints for debugging MySQL InnoDB deadlocks

Deadlocks only occur if two transactions in separate threads compete for the same rows in the database. They usually (but not necessarily) only happen when trying to update or otherwise lock several rows in different order.

Solving deadlocks is potentially complicated, so here are a few pointers:

  • MySQL should always detect the deadlock right when it happens, and will throw an error to one of the offending threads. This error states the SQL statement that this thread was currently waiting for, and that tried to acquire one of the competin…
Repeats

Rails: How to use prepend to avoid monkey patches in modules

Let's say you have a gem which has the following module:

module SuperClient

  def self.foo
    'Foo'
  end
  
  def bar
    'Bar'
  end

end

For reasons you need to override foo and bar.

Keep in mind: Your code quality is getting worse with with each prepend (other developers are not happy to find many library extensions). Try to avoid it if possible.

  1. Add a lib/ext/super_client.rb to your project (Folder or file needs to be required in an initializer)
  2. Add the extension, which overrides both methods (prepend i…
Linked contentRepeats

How to write a good changelog

We want to keep a changelog for all gems we maintain. There are some good practices for writing a changelog that adds value, please stick to these.

  • Add a notice to the README's contribute section about the changelog
  • For every release update the changelog
  • Note the date format yyyy-mm-tt

What is a changelog?

A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.

Why keep a changelog?

To make it easier for users and…

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 = /...

Repeats

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…
Repeats

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 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.

Simply SSH to the remote machine (e.g. to your office PC) and add -X to the ssh call. Now, when you start a program with an UI (e.g. virtualbox) in that SSH session, a window will open on your local machine. It will not be particularly snappy, but on a decent connection it will be usable. …

Repeats

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

Developer

  • 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…
Repeats

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…

Repeats

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

Example:

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.

RepeatsDeprecated

Trigger native mouse events with Javascript

The attached Coffeescript helper will let you create mouse events:

$element = $('div')
Trigger.mouseover($element)
Trigger.mouseenter($element)
Trigger.mousedown($element)
Trigger.mouseup($element)
Trigger.mouseout($element)
Trigger.mouseleave($element)
Trigger.click($element)

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…
Repeats

Trigger a link's click action with Javascript

TLDR

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

$link = $('a:first');
$link[0].click()

Mind the [0].

Long story

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

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

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....
Repeats

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?

private

def office_people_count_needs_update?
  office_id_changed? || trashed_changed?
end

Or, move t…

This website uses cookies to improve usability and analyze traffic.
Accept or learn more