Today I Learned

Extend Ecto's query API with your own macros

Imagine for a second this is something you're using a lot when programming Elixir and Phoenix:

    from u in User,
        where: fragment("lower(?)", u.email) == ^email

You can write your own Elixir macro to improve your flow.

defmacro lower(arg) do
    quote do: fragment("lower(?)", unquote(arg))

Then your query can be rewritten like this:

    from u in User,
        where: lower(u.email) == ^email

How to change JPEG compression rate in WordPress

Our client wants pixel perfect images in his WordPress site. Truth is WordPress is a bit agressive in compressing JPEGs.

WordPress default is 75% compression quality. A higher setting will generate better looking images, to the expense of larger filesize.

Add this to your functions.php file:

// Change JPEG compression rate - 85 is much more reasonable setting
$jpeg_compression = function() { 
    return 85; 

add_filter( 'jpeg_quality', $jpeg_compression );

Advance Custom Fields' textarea newline behaviour in Wordpress

Have you ever wondered why ACF's textarea field adds <br>s in your frontend html instead of a paragraph tag? An this happens in spite of the explicit newline settings on the fields

It turns out this is the default behaviour and it's a rather common pitfall for many ACF newcomers.

Here's the deal:

Hit Enter twice for a paragraph p.
Hit it just once for a regular single line break <br>.

The importance of expressive, namespaced html attributes

Here's another reminder why expressive, namespaced ids are important. This time is about a label's for attribute.

<input id="phone">
<label for="phone"></label

This would work just as expected unless, for example, we have a svg sprite at the beginning of the document that includes an svg with a "phone" id.

<symbol id="phone" viewBox="0 0 61.4 48">...</symbol>
<input id="phone">
<label for="phone"></label

In this case, the label's for will match the first in a top-down order that has the target id.

And you will never know why clicking the label won't trigger the input.

How to validate your password with regex

Example password validation regex

  • rules below can be concatenated

Special character matching

  • Matches (operator is ?=) any string that has at least a special character e.g.: sadsds@asdasd

Number matching

  • Matches (operator is ?=) any string that has at least a number: e.g.: s1adsdsasdasd

Small letter matching

  • Matches (operator is ?=) any string that has at least a small letter: e.g.: SADSa

Big letter matching

  • Matches (operator is ?=) any string that has at least a big letter: e.g.: SADSa

Consecutive numbers matching

  • Doesn't match (operator is ?!) strings that have consecutive numbers in them: e.g.: asdasd42dada

Sequential numbers matching (cannot be used at the same time with previous rule)

  • Doesn't match (operator is ?!) strings that have sequential numbers in them: e.g.: 12asdasd42dada
  • It will allow numbers that are separated by other letters e.g.: adasd1asd2asd3
  • It will allow consecutive numbers e.g.: ahadADS22dhsg44

Length of string matching (should be placed last)

  • This will match any string that is less than 8 characters

You can write better jQuery. A DRY approach to multiple configurations

From this
    buttonClass: 'btn btn-default',
    buttonWidth: '100%',
    buttonClass: 'btn btn-default',
    buttonWidth: '100%',
    nonSelectedText: '---',
To This
<select class="js-multiselect" 
$('.js-multi-select).each(function () {
    let options = {};

        .map(property => options[property[0]] = property[1]);



And never go back for adjustments in the script file ever again.

Work with "unsafe" HTTPS connections on localhost in Chrome

If you work with HTTPS connections on your localhost development environment, you will often get an un-secure notification from Chrome, and this will be getting annoying.

To disable those notifications in Chrome type this in your address bar:


search for:

Allow invalid certificates for resources loaded from localhost.

and click on "Enable". Done!

As a precaution: You should use separate browsers for personal use and another for development. I do development in Chromium and my regular browsing in Safari.

.times in JavaScript

Never modify JavaScript's standard built-in objects. That's what they say.

But you're at this hackathon stuck with JS missing Ruby's .times iterator and that's what JS's prototypes are for after all.

Here's how you do it:

String.prototype.times = function (n) {
    for (var i = 0; i < parseInt(this); i++) {
var myFunc = function () { console.log('Hello World') }


"Hello World"
"Hello World"