All articles

Extension Fields

Category:

Extension Fields are a standard YAML feature that helps you avoid repeating yourself in configuration files.

base_character_stats: &base_stats
  hp: 100
  mp: 50
  level: 1
  inventory_size: 10
  faction: "neutral"

characters:
  player_warrior:
    name: "Conan"
    class: "Warrior"
    <<: *base_stats
    weapon: "Sword"

  boss_orc:
    name: "Grommash"
    class: "Warchief"
    <<: *base_stats
    # You can still override things
    hp: 500
    faction: "horde"
    special_ability: "Rage"

Universal Development Environment Setup Guide

Category:

Install Windows Terminal

Windows Terminal is a modern app that lets you use different command lines like PowerShell and WSL in one window with tabs.

Get it from the Microsoft Store.

Install VS Code and Extensions

VS Code is a free and popular code editor.

Download it from code.visualstudio.com.

If you already have it, update it from the menu Help -> Check for Updates.

Install the WSL extension. This lets you open your Linux project folders in VS Code.

Install the Dev Containers extension. This lets you connect VS Code to a running Docker container. This is essential, because without it, your code editor cannot see the project’s dependencies that are only installed inside the container. By connecting, you get full code completion and suggestions (IntelliSense).

Install WSL2 (Windows Subsystem for Linux)

WSL2 lets you run a real Linux system (like Debian) inside Windows.

To update WSL if you have it, run this command in PowerShell:

wsl --update

To see which Linux systems you have, run:

wsl -l -v

If you don’t have Debian, install it:

wsl --install -d Debian

(Optional) To remove a Linux system you don’t need:

wsl --unregister Ubuntu-20.04

Install Docker Desktop

Docker Desktop is an app that helps you build and run applications in containers.

Download it from www.docker.com/products/docker-desktop/.

After installing, go to  Settings -> Resources -> WSL Integration  and make sure the switch for Debian is turned on.

Configure Debian

Inside your Debian terminal, install and set up Git:

sudo apt update && sudo apt upgrade -y
sudo apt install git
git config --global user.name "Twoje Imię"
git config --global user.email "twoj.email@example.com"
git config --global credential.helper cache

Install curl:

sudo apt-get install curl

Install and configure bash-completion:

sudo apt-get install bash-completion
sudo curl -L https://raw.githubusercontent.com/docker/compose/v2.24.6/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose

Workflow

This is the standard process for working on any project.

  1. Open  Windows Terminal  to launch the  Debian WSL  shell. It’s best to have a projects directory in your home folder (~) to keep all your work organized. This is where you will use Git and Docker (the docker command will interact with Docker Desktop).
  2. In the ~/projects directory, clone your repositories and run Git commands.
  3. If needed, create a .env file for the project.
  4. If needed, start the project’s containers (e.g., with docker compose up -d).
  5. In  VS Code , connect to either  WSL  or a  container , depending on your needs. Connecting to a container allows you to edit code inside of it (this makes sense for projects using bind mounts) and gives your IntelliSense access to dependencies that are only installed inside the container (which is the recommended setup).

Glossary

Category:
Emacs term Term for normal people
A- C-x 8
Buffer An opened file or other thing like game, help, Messages, etc.
Copy as kill Copy.
Faces Fonts.
Frame Emacs window.
Fringes Margins on left, right or both sides of the window.
Kill Kill buffer = close buffer. Kill text = cut text.
Meta key Alt key.
Window Panel where buffers can be displayed.
Yank Paste (like copy and paste).

map vs pluck

Category:

Both methods return the same output (an array of strings).

Article.all.map{|a| a.title}
Article.pluck(:title)

But they do that in different ways.

SQL query generated by all:

SELECT "articles".* FROM "articles"

It fetches all atributes, then it converts the collection with map method.

SQL query generated by pluck (or .all.pluck):

SELECT "articles"."title" FROM "articles"

pluck is faster.

Depth First Search

Category:

The graph is given.

An image of graph

Graph as a hash:

graph = {
    0 => [1,9],
    1 => [0,8],
    2 => [3],
    3 => [2,4,5,7],
    4 => [3],
    5 => [3,6],
    6 => [5,7],
    7 => [3,6,11,10,8],
    8 => [1,7,9],
    9 => [0,8],
    10 => [7,11],
    11 => [7,10],
    12 => [],
}

Algorithm code with a loop instead of recursion

def dfs(graph, start_node)
  current_node = start_node
  stack = [start_node]
  visited = [start_node]
  loop do
    p "stack: #{stack}"
    p "visited: #{visited}"
    unvisited_neighbour = graph[current_node].find do |node|
      !visited.include?(node)
    end
    if unvisited_neighbour
      current_node = unvisited_neighbour
      visited << current_node
      stack << current_node
      next
    else
      stack.pop
      current_node = stack.last
      break unless current_node
    end
  end
end

dfs(graph, 0)

String vs Symbol

Category:

String

Is a sequence of bytes. The text is converted into those bytes usually by UTF-8 encoding.

String object are mutable.

Symbol

Symbol objects are immutable.

Same symbols, for example :book and :book, are in fact one object that is shared globally in all contexts for the duration of a program’s execution.

Thanks to that sharing symbols costs less memory than strings, but they cannot be collected by Garbage Collector once created.

Comparing symbols is quicker than comparing strings.

Datatypes in Postgresql and Rails

Category:
Postgresql type name in Rails Rails type
text text String
box box String
polygon polygon String
circle circle String
timestamp datetime ActiveSupport::TimeWithZone
time time ActiveSupport::TimeWithZone
date date Date
json json String
point point ActiveRecord::Point
boolean boolean TrueClass/FalseClass
path path String
xml xml String
jsonb jsonb String
bit bit String
inet inet IPAddr
float float Float
daterange daterange Date…Date
tsrange tsrange Time…Time
integer integer Integer
money money BigDecimal
uuid uuid String
numrange numrange BigDecimal..BigDecimal
decimal decimal BigDecimal

Directed graph by "has_many through"

Category:

My model will be called Node, and I want to connect them with other nodes in a way that is called “directed graph”.

an image of a directed graph

An example of a directed graph from Wikimedia Commons.

Each node can have zero, one or many children, and zero, one or many parents. To do this I need an another model which will represent connections between nodes. I assume that Node model already exists and I will create the NodeConnection model by generating a scaffold.

rails g scaffold NodeConnection child:references parent:references --no-stylesheets

Nodes will be connected with other nodes, but I can’t make two column with the same “node” name. Instead of that the names are “child” and “parent”. I think the same result can be achived by child_id:integer parent_id:integer instead of child:references parent:references.

An auto-generated migration is OK, I don’t need to add anything at this moment, so I can migrate.

rake db:migrate

The associations in the NodeConnection model file should have additional arguments.

class NodeConnection < ActiveRecord::Base
  belongs_to :parent, class_name: 'Node', foreign_key: 'parent_id'
  belongs_to :child, class_name: 'Node', foreign_key: 'child_id'
end

And an assiociation in the Node model file:

class Node < ActiveRecord::Base
  has_many :parent_connections, foreign_key: 'child_id', class_name: 'NodeConnection'
  has_many :parents, through: :parent_connections

  has_many :child_connections, foreign_key: 'parent_id', class_name: 'NodeConnection'
  has_many :children, through: :child_connections
end

For each node there are now methods parents and children avaliable.

Cron

Category:

Crontab commands

Edit user’s crontab

crontab -e

List user’s crontab

crontab -l

Delete user’s crontab

crontab -r

Crontab examples

On every minute

* * * * * /scripts/foo.sh

On every 5 minutes

*/5 * * * * /scripts/foo.sh

At midnight on first day of every month

0 0 1 * * /scripts/foo.sh

On every 30 seconds

* * * * * /scripts/foo.sh
* * * * * sleep 30; /scripts/foo.sh

At night on last day of every month

0 3 28-31 * * test $(date -d tomorrow +%d) -eq 1 && /scripts/foo.sh