Today I Learned

A Hashrocket project

Ready to join Hashrocket? Find Openings here and apply today.

How to force reload associations in Ecto

Ecto by default doesn’t load associations and you have to explicitly call preload:

id = 1
user = Repo.get(User, id) |> Repo.preload(:posts)

If you call preload again on the same user, Ecto won’t make the SQL query again because the association is already loaded:

user = user |> Repo.preload(:posts)

But in some cases you do want to reload a preloaded association then you can use force: true:

user = user |> Repo.preload(:posts, force: true)

Disable capture in Elixir Regex

Today I came across a regex that had to use the ( parenthesis to match a sequence of chars but I wanted just to match them, so I’d love if I could ignore that piece from the “capture” part.

So I learned that we could use ?: in the beginning of the ( and that would turn the capture off for that piece. Check this out;

iex> Regex.scan(~r/aa(bb)(?:cc|CC)/, "aabbccdd aabbCCdd")
[["aabbcc", "bb"], ["aabbCC", "bb"]]

In this case I am matching and capturing the bb sequence and I am matching but not capturing the cc|CC sequence options.

Set JSON.parse returned object and array classes

By default, the Ruby JSON.parse method returns a ruby Hash for any json object, and a ruby Array for any json array.

However, you can customize the returned object classes using the object_class and array_class options:

source = JSON.dump({ wibble: "wubble", data: [1,2,3] })

result = JSON.parse(
  source, 
  object_class: OpenStruct,
  array_class: Set
)
# => #<OpenStruct wibble="wubble", data=#<Set: {1, 2, 3}>>

result.data # => #<Set: {1, 2, 3}>
result.wibble # => "wubble"

Add a folder to git with exceptions

Given this folder structure:

app
├── bin
│  └── parse-ansi-codes.rs
├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│  ├── cursor.rs
│  ├── lib.rs
│  └── style.rs
├── target
│  └── debug
└── test

I can add the entire app directory to git, while ignoring the bin folder:

$ git add . ':!bin'

rspec should receive thrice

rspec has a #thrice method for testing receive counts:

describe Account do
  context "when opened" do
    it "logger#account_opened was called once" do
      logger = double("logger")
      account = Account.new
      account.logger = logger

      logger.should_receive(:account_opened).thrice

      account.open
      account.open
      account.open
    end
  end
end

Replace multiple characters in ruby strings

Ruby String#tr allows you to replace characters or patterns in strings:

irb(main):001:0> "I love coffee".tr("love", "😍")
=> "I 😍😍😍😍 c😍ff😍😍"

Compare with #gsub:

irb(main):001:0> "I love coffee".gsub("love", "😍")
=> "I 😍 coffee"

If your pattern arg to gsub is only one character consider using #tr, but beware of multi-length from_str arg to #tr

Split text in postgres

You can split text in postgres

select email from users;
bob@example.com
mary@example.com
select split_part(email, '@', 1) from users;
bob
mary
select split_part(email, '@', 2) from users;
@example.com
@example.com

Which can be helpful when sanitizing data:

update users
  set email = split_part(email, '@', 1) || '@example.com';

List cli xcodebuild archives in Xcode's organizer

When using a Makefile to build Xcode applications, it’s nice to have the archives listed in the Organizer window, for easy distribution. This can be accomplished with the -archivePath flag, using a specific directory:

BOB_THE_BUILD_DIR="~/Library/Developer/Xcode/Archives/$(date +%Y-%m-%d)"
ARCHIVE_PATH="$BOB_THE_BUILD_DIR/MyApp-$(date|md5).xcarchive"

xcodebuild -scheme MyApp -workspace "MyApp.xcworkspace" archive -configuration release -archivePath "$ARCHIVE_PATH"

Preview ffmpeg video filters without re-encoding

I was playing around with some ffmpegfilters, like cropping, scaling and overlays and I was tired of waiting for the video to be fully re-encoded in order to see the changes.

ffmpeg -i video.mp4 -vf "crop=in_w:in_h/2:0:0" -c:a copy output.mp4

I’m glad that this is not a problem because you can use ffplay to preview the changes instantly without having to wait:

ffplay -i video.mp4 -vf "crop=in_w:in_h/2:0:0"

How to conditionally add a value in array literals

I really like declarative things. It’s probably why I like React, and really dig functional programming approaches. So when I’m writing Ruby, sometimes I find myself wanting to delcare some array of values to use in a map, reduce, or each. The problem is, sometimes I only want a particular value give a condition. One pattern that I’ve started to try on for size is

def things
  [something, (something_else if reasons)]
end

Then, you can use it like so:

things.compact.map(&:cool_method)

The conditional will evaluate and leave a nil in the array, which isn’t my favorite. However, I’ve found that this is a very useful pattern for simplifying certain methods.

When to set `inverse_of` in Rails AR

Rails ActiveRecord does not auto infer bi-directional associations if some of the associations contains a scope or any of the following through or foreign_key options.

class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
irb> a = Author.first
irb> b = a.books.first
irb> a.first_name = 'David'
irb> a.id = b.writer.id
=> true
irb> a.object_id = b.writer.object_id
=> false
irb> a.first_name == b.writer.first_name
=> false

To solve this issue we should use inverse_of option, check this out:

class Author < ApplicationRecord
  has_many :books, inverse_of: 'writer'
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
irb> a = Author.first
irb> b = a.books.first
irb> a.first_name = 'David'
irb> a.id = b.writer.id
=> true
irb> a.object_id = b.writer.object_id
=> true
irb> a.first_name == b.writer.first_name
=> true

Github Resolving Git Conflicts

Today I tried out Github to Resolve Git Conflicts of an open PR. I noticed that Github has this gray button Resolve conflicts:

image

Then it drives me to a managing conflicts page with a simple editor where I could manually choose and edit the conflicts:

image

After my editing is done I can Mark as resolved:

image

And finally I can Commit merge:

image

Wait, what? oh no, I know that merging is the easiest way to solve conflicts as you solve all conflicts once, no matter how many commits your branch has, but to be honest I did not like that. I put some small effort to keep my git history clean and I really avoid merge commits as they are not necessary in general. I tend to keep a single history line on my git repos in the main branch, most of the times at least.

I guess that it is what it is, every time we use a tool to “simplify” the work we are giving up a bit of control on how the things are executed, right?

So here’s the resolve of Github’s solving git conflicts flow:

image

Preloading data for Phoenix LiveView components

One of the most common problems in web development is N+1. Graphql has taught me the DataLoader pattern and since then I never had to worry about N+1 as long as I kept using that pattern.

With Phoenix LiveView you don’t need to think about APIs anymore but I’m glad that it has support for preloading data kind of the same way as if it was a DataLoader. You can define a preload function that will receive a list of all the assigns so you can preload all the data needed for multiple components in one single batch before they are mounted. Here is the sequence of a component lifecycle:

preload(list_of_assigns) -> mount(socket) -> update(assigns, socket) -> render(assigns)

On this example only one SQL query is made to load all products by id:

@impl true
def preload(list_of_assigns) do
  product_ids = Enum.map(list_of_assigns, & &1.product_id)

  products =
    from(p in Product, where: p.id in ^product_ids, select: {p.id, p})
    |> Repo.all()
    |> Map.new()

  Enum.map(list_of_assigns, fn assigns ->
    Map.put(assigns, :product, products[assigns.product_id])
  end)
end

Conditionally Render Rails Links with `link_to_if`

ActionView::Helpers contains some really handy helpers for conditionally rendering links. For example, the link_to_if method will render the link if the given condition is met; otherwise it renders just the text.

<%= link_to_if(current_user.present?, "Admin Panel Tools", admin_tools_path) %>

When current_user.present? is true, yields the following HTML:

<a href="/admin_tools">Admin Panel Tools</a>

But when current_user.present? is false, yields the following:

Admin Panel Tools

https://api.rubyonrails.org/v6.0.2.1/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to_if

Note, there are also methods for link_to_unless and link_to_unless_current

Elixir Supervisor default child_spec

When using Supervisor elixir already declares a child_spec/1 for us with the right type: :supervisor. The generated code will be something like:

defmodule MyApp.MySupervisor do
  use Supervisor, opts
  
  ...

  def child_spec(init_arg) do
    default = %{
      id: __MODULE__,
      start: {__MODULE__, :start_link, [init_arg]},
      type: :supervisor
    }

    Supervisor.child_spec(default, unquote(Macro.escape(opts)))
  end
end

Keep in mind that’s a pseudo-code as I left the Macro.escape for better understanding of the “expanded” code that happens on the __using__/1 function.

I tried to get this info from the docs, which I could not find that easily so I dig into the code, and as a good surprise this was so easy to find. Check this out.

By the way, the generated code is very similar to the GenServer one for the same function, the only difference is that on the GenServer there’s no :type key, and it works fine because the default value for the :type key is :worker.

Javascript Privates

You can utilize ‘private’ features in a javascript class via the # character prepending a name. They are referred to as ‘hash names’.

These private fields must be declared ahead of time otherwise they will result in a syntax error.

For this example I replaced some declaratively ‘private’ attributes _closed & _balance with actual ‘private’ attributes #closed & #balance.

export class BankAccount {
  #closed
  #balance
  
  set balance(amount) {
    return this.#balance = amount;
  }

  get opened() {
    return !this.closed;
  }

  get closed() {
    return this.#closed == true;
  }
}

It appears that if you’re at Node 12 or higher you can use this functionality.

You can read more about this at MDN

How using fzf in new places rocks

Thanks to joshbranchaud and gabrielreis for these:

Fuzzy git checkout (alias in git config):

[alias]
    fco = !git branch | fzf +m | awk '{print $1}' | xargs git checkout

Then just use git fco and get an interactive fzf session to look through the available branches!

Fuzzy rails routes:

rails routes | fzf

Fuzzy search your routes without needing to run rails routes multiple times!

Using `@describetag` in Elixir Tests

Wow! ExUnit have some special tags for @moduletag and @describetag which are self explanatory if you know what tags are used for in ExUnit. They are so useful in case you want to, for example, only run that section of tests:

defmodule MyApp.AccountsTest do
  use MyApp.DataCase

  @moduletag :module_tag

  describe "search" do
    @describetag :describe_tag

    @tag :test_tag
    test "return all users" do
      user_1 = insert!(User)
      user_2 = insert!(User)

      assert Accounts.search(User) == [user_1, user_2]
    end
    ...
  end
  ...
end

In case you want to run only tests that match with a module (file) level @moduletag:

my_app git:(main) ✗ mix test --only my_module_tag
Excluding tags: [:test]
Including tags: [:my_module_tag]
............
Finished in 0.2 seconds
22 tests, 0 failures, 10 excluded

Or if we want to run all tests that match with a describe block tagged with @describetag:

my_app git:(main) ✗ mix test --only my_describe_tag
Excluding tags: [:test]
Including tags: [:my_describe_tag]
....
Finished in 0.2 seconds
22 tests, 0 failures, 18 excluded

We can see by the number of excluded tests that this works great as expected.

Nullish coalescing operator - ??

Ever need to have a back up default value when something is null or undefined in Javascript? Well a fairly recent addition to JS has got you covered. The Nullish coalescing operator?? may help you on your logical path.

If the first half of the epresssion is ‘nullish’, it will return the latter.

const defaultValue = 'I WIN'
const someVariable = null
someVariable ?? defaultValue
=> 'I WIN'

compare this to using || in which the first half of expression needs to evaluate falsey to get into the latter portion.

As it is a newer part of the JS API make sure to check for browser support. There is also a polyfill available.

How to show constraints in MySQL

Working in Postgres, I’ve gotten used to seeing the contraints on a table listed with \d. Working in MySQL I wasn’t seeing similar with describe <table>;. Turns out you can see all the constraints by selecting from information_schema.referential_constraints:

SELECT * 
  FROM information_schema.referential_constraints 
  WHERE constraint_schema='db_name' 
  AND table_name='table_of_interest';

React SyntheticEvent for Focus and Blur

Some JavaScript events like focus and blur do not bubble to parent elements. Let’s say that we have:

<div
  onfocus="console.log('div focus')"
  onblur="console.log('div blur')"
>
  <input
    type="text"
    placeholder="Type something here"
    onfocus="console.log('input focus')"
    onblur="console.log('input blur')"
  >
</div>

Then if we focus we’ll see in the console input focus and if we blur we’ll see input blur. This makes a lot of sense as a div does not have the concept to focus, there’s no blinking cursor or anything like that.

But in React the scenario is different. In an attempt to standardize all browser events to behave similarly to each other and across different browsers, React wraps all events in SyntheticEvents and for the onFocus and onBlur events we’ll see that they do bubble up:

<div
  onFocus={() => console.log('div focus')}
  onBlur={() => console.log('div blur')}
>
  <input
    type="text"
    placeholder="Type something here"
    onFocus={() => console.log('input focus')}
    onBlur={() => console.log('input blur')}
  />
</div>

Here if we focus we’ll see input focus and div focus in this order and if we blur we’ll see input blur and div blur in this order again.

Use reduced motion to control a video

I used my useWatchMedia hook to play/pause a video based on the reduced motion OS config.

On Macs you can set this option in System Preferences => Accessibility => Display:

image

This way users with motion sickness can have better time browsing your website.

And here’s my video component:

const useReducedMotion = () => {
  return useWatchMedia('(prefers-reduced-motion: reduce)');
};
const MyVideo = ({url}) => {
  const ref = useRef();
  const reducedMotion = useReducedMotion();

  useLayoutEffect(() => {
    if (ref.current) {
      reducedMotion ? ref.current.pause() : ref.current.play();
    }
  }, [ref, reducedMotion]);

  return (
    <video autoPlay loop muted playsInline ref={ref} src={url} />
  );
};

As the browser exposes this config via media query we could also use regular css for that media to enable/disable features, for example css animations.

About cool ways to use file marks

File marks in vim are just marks made with [A-Z]. They have the delightful property that they persist (via .viminfo) across sessions without needing a session (depending on your settings). I’ve known about them for a while, but I wasn’t sure if there was really a way that I could come up with the use them. So I went out looking and found something that I like!

`T -> project todo file
`V -> .vimrc

I’ll probably come up with some other ideas based on the invariant files that I frequently visit, but these two are definitely going into my rotation. I’m also thinking that at least one more should be added:

`L -> TIL file (ABT - always be TILin)

cReddit where credit is due

About rspec test tags

You want a way to run a specific sub-set of your specs. Well RSpec has a tag metadata that you can add to make things a lot nicer:

describe "my awesome code", :awesome do
  # some set of awesome tests
end

Now I just run rspec --tag awesome and you’re just going to run your block!

It also takes a negation, which means that if you want to run everything else you just use rspec --tag ~awesome.

You can also use this to add behavior to the way examples are dealt with via RSpec.configure

RSpec.configure do |config|
  config.append_after : each do |ce|
    if ce.metadata[:awesome]
         # do something awesome to the example
    end
  end
end

Phoenix LiveView with some JSX flavor

Today I learned from Vinny about this Elixir library called Surface that allows you to write LiveView components that look a lot like JSX from React.

You first create a module that uses Surface.Component and define some props:

defmodule MyApp.WelcomeMessage do
  use Surface.Component

  prop name, :string, required: true

  def render(assigns) do
    ~F"""
    <div class="title">Hello, <strong>{@name}!</strong><div>
    """
  end
end

Then your LiveView module needs to use Surface.LiveView and you are ready to render that new “JSX” component passing some props:

defmodule MyApp.ExampleLive do
  use Surface.LiveView
  alias MyApp.WelcomeMessage

  def render(assigns) do
    ~F"""
    <div class="container">
      <WelcomeMessage name="Vinny" />
    </div>
    """
  end
end

Surface also handles state and has a way to handle portals, which are called slots. I might play with this library in one of my side-projects.

About `:aggregate_failures` for rspec

When writing rspec tests you can separate your test cases as in:

describe "foo" do
  specify { expect(some_behavior).to be_well_behaved }
  specify { expect(some_other_behavior).to be_well_behaved }
end

Or if you prefer to write:

describe "foo" do
  it "handles some behaviors" do
    expect(some_behavior).to be_well_behaved
    expect(some_other_behavior).to be_well_behaved
  end
end

The second example has the downside that it will fail out of the it block if the first expect doesn’t pass. To get around this, you can use:

describe "foo" do
  it "handles some behaviors", :aggregate_failures do
    expect(some_behavior).to be_well_behaved
    expect(some_other_behavior).to be_well_behaved
  end
end

Which will run the specs and collect their failures.

Watch Media query changes using React hooks

I end up creating a React hook to watch a media query change. I am using window.matchMedia to achieve that. Check this out:

const useWatchMedia = (media) => {
  const [matches, setMatches] = useState();

  useEffect(() => {
    const watchedMedia = window.matchMedia(media);
    const mediaListener = () => setMatches(watchedMedia.matches);

    mediaListener();
    watchedMedia.addListener(mediaListener);

    return () => watchedMedia.removeListener(mediaListener);
  }, [media]);

  return matches;
};

React hooks are an excellent way to share this setup (and cleanup)!

Nested attributes in Phoenix (Live) Views:

To use nested attributes in a form you have to use the inputs_for helper:

<%= f = form_for @changeset, Routes.user_path(@socket, :create), phx_submit: :submit, as: :user %>
  <%= input f, :name %>
  <%= inputs_for f, :address, fn a -> %>
    <%= input a, :city %>
    <%= input a, :zipcode %>
    <% end %><
  <%= submit "Create" %>
</form>

And then you can use cast_assoc and specify the changeset for the nested schema you want to validate:

defmodule MyApp.User do
  def registration_changeset(user, attrs, opts \\ []) do
    user
      |> cast(attrs, [:name])
      |> cast_assoc(:address, with: &MyApp.Address.changeset/2)
      |> validate_required([:name, :address])
  end
end

defmodule MyApp.Address do
  def changeset(address, attrs, opts \\ []) do
    user
      |> cast(attrs, [:city, :zipcode])
      |> validate_required([:city, :zipcode])
  end
end

About nvim SHADA (Shared Data) file and Sessions

Ever stop your vim and get really depressed that you just lost your buffers? Cause I’ve done it twice today. The relevant details about sessions:

   The following command creates a session file:

    :mksession vimbook.vim

Later if you want to restore this session, you can use this command:

    :source vimbook.vim

If you want to start Vim and restore a specific session, you can use the
following command:

    vim -S vimbook.vim

This tells Vim to read a specific file on startup.  The 'S' stands for
session (actually, you can source any Vim script with -S, thus it might as
well stand for "source").

Your sessionoptions needs to include buffers. The SHADA file is like adding steroids. You can keep marks, register contents, and command line history.

Relevant documentation

React `useImperativeHandle` hook

I end up using useImperativeHandle hook to extract a component to be reusable. In this case I am using react-google-recaptcha lib for captcha and I have to pass a ref so the lib can bind some functions to that. Let’s see how I got to expose a function to the parent component via ref:

import React, {useRef, useImperativeHandle, forwardRef} from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

const Captcha = (_props, ref) => {
  const captchaRef = useRef();

  useImperativeHandle(ref, () => ({
    executeAsync: () => {
      captchaRef.current.executeAsync();
    },
  }));

  return (
    <ReCAPTCHA ref={captchaRef} sitekey="some key here" />
  );
};

export default forwardRef(Captcha);

I had to use both useImperativeHandle and forwardRef in order to receive the ref from the parent and “forward” to the ref internal to this component.

And here’s how I am calling that:

const MyForm = () => {
  const captchaRef = useRef();

  const onSubmit = async (values) => {
    const recaptchaToken = await captchaRef.current?.executeAsync();
    placeOrder({recaptchaToken, ...values});
  };

  ...

  return (
    <form onSubmit={onSubmit}>
      ...
      <Captcha ref={captchaRef} />
      <input type="submit" value="Save" />
    </form>
  );
};

Although this is a very unusual thing to do in React, it was necessary in order to extract this component.

Session cookie with Phoenix LiveView

You can use phx-trigger-action to make sure a form submit goes through http instead through the socket.

On the example below, when @trigger_submit is true then the form will be sumitted to the path Routes.user_session_path(@socket, :create), which will hit the controller and set the cookie:

<%= f = form_for @changeset, Routes.user_session_path(@socket, :create), phx_trigger_action: @trigger_submit, phx_change: :validate, phx_submit: :submit, as: :user %>
  <%= input f, :email %>
  <%= input f, :password %>
  <%= submit "Sign In", disabled: !@changeset.valid? %>
</form>

RSpec's Render Template is Permissive

In a controller test, when you expect a request to render a template, you’d write something like this:

expect(response).to render_template(new_user_path)

If your controller action looked like the following, the expectation would pass:

class UsersController < ActionController::Base
  def action
    ...
    render :new
  end
end

render_template delegates to ActionController::TemplateAssertions#assert_template. What I didn’t know, however, is how permissive (magical) it is.

Let’s say instead of the action’s render :new you returned a json object with the template, rendered to a string, as one of its values:

def action
  response_body = render_to_string(layout: false, template: "users/new.html.haml")
  render json: { page: response_body }
end

expect(response).to render_template(new_user_path) still passess!!!

Also if you say expect(response).to render_template("new.html.haml"), it also passes. How does it know you meant the user’s new.html.haml and not some other arbitrary one? Maybe because you’re in the UsersControllerSpec. You can also expect...render_template for templates unrelated to the controller’s scope.

I suspect that this permissiveness is caused by Rails registering the rendering of templates, irrespective of whether they are rendered to strings or directly as a response to a controller action. expect...render_template maybe then looks through the registered renders 🤷🏾‍♂️. Either way, it’s magical!

Easily Format Phone Numbers in Rails

Included as part of ActiveSupport, Rails has a handy helper for formatting phone numbers. Passing a number/string to the helper and some optional args and it will take care of the rest.

Here’s a few examples of how it works:

number_to_phone(8858846) # 885-8846
number_to_phone(8778858846) # 877-885-8846
number_to_phone(8778858846, area_code: true) # (877) 885-8846

To see all the options for the method, check out the Rails docs https://api.rubyonrails.org/classes/ActiveSupport/NumberHelper.html#method-i-number_to_phone

🚯 Prevent development logs from bloating on macOS

I rarely need to refer to development.log or test.log when working on rails applications, but yet I end up keeping weeks or even years of records [gigabytes]. I’m used to working with logrotate, and I wanted to find a similar solution that was preinstalled with macOS. macOS comes preinstalled with a program called newsyslog that can keep file sizes in check. I just created a new file at /etc/newsyslog.d/rails.conf which limits all rail’s log files to just 10MB

# /etc/newsyslog.d/rails.conf
# logfilename                                                   [owner:group]      mode count size(KB)     when  flags [/pid_file] [sig_num]
/Users/<username>/dev/<rails projects>/*/log/*.log              <username>:staff   644  0     10000         *     G
# Mono repos
/Users/<username>/dev/<rails projects>/*/*/log/*.log            <username>:staff   644  0     10000         *     G
# Deeper mono repos
/Users/<username>/dev/<rails projects>/*/*/*/log/*.log          <username>:staff   644  0     10000         *     G

You can also perform a dryrun of the config for testing:

sudo newsyslog -v -n -f /etc/newsyslog.d/rails.conf