Create a working copy from a bare git repository

Bare git repositories don’t have a working copy where you can read and edit files. Instead it contains what is usually in the .git subdirectory of a repository. You can re-create a “traditional” repository by cloning the bare repository.

git clone --local bare-repo-path project-name
2019-12-10 by Dimiter Petrov

Ruby: Use cover? instead of include? for ranges

include? compares every object of an array, while cover? checks if an item fits between the end points.

This difference makes it much faster to use cover? for ranges.

Example:

    one_hundert_years_ago = Date.today - 100.years
    today = Date.today

    t = Time.now
    (one_hundert_years_ago..today).include?(Date.tomorrow)
    puts Time.now - t
    # => 0.029056

    t = Time.now
    (one_hundert_years_ago..today).cover?(Date.tomorrow)
    puts Time.now - t 
    # => 3.4e-05 (= 0.000034)
2019-11-26 by Mischa Steiner

git stash --include-untracked

Let’s say you have modified a file in a git repository and have also created a new file, but not added it to the repository yet:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    notes.txt

no changes added to commit (use "git add" and/or "git commit -a")

If you run git stash, the untracked file remains in the working copy:

$ git stash
Saved working directory and index state WIP on master: 0f25a2b Initial commit
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    notes.txt

nothing added to commit but untracked files present (use "git add" to track)

Chances are the untracked files are related to the change you are trying to make and would like to bundle them in that stash.

The --include-untracked option (or -u in its short version) allows you to do just that:

$ git stash -u
Saved working directory and index state WIP on master: 0f25a2b Initial commit
$ git status
On branch master
nothing to commit, working tree clean

That’s a nice alternative to adding the untracked files and making a “work in progress” commit.

2019-11-26 by Dimiter Petrov

ActionDispatch::SystemTestCase no longer inherits from ActionDispatch::IntegrationTest in Rails 6.0.1

With Rails Release 6.0.1, ActionPack comes with this breaking change:

ActionDispatch::SystemTestCase now inherits from ActiveSupport::TestCase rather than ActionDispatch::IntegrationTest

Link to CHANGELOG

That means that some useful helper methods won’t be available anymore in system tests.

In one project we use a method fixture_file_upload that was affected by this change. We brought this back by including the corresponding module in ApplicationSystemTestCase:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  include ActionDispatch::TestProcess::FixtureFile

  # ...
end
2019-11-08 by Mario Schüttel

Adding a limit to ActiveRecord "last" method

ActiveRecord supports adding a LIMIT to your SELECT statement through the last method:

User.last(10)

results in the following SQL query:

User Load (0.4ms)  SELECT `users`.* 
FROM `users` ORDER BY `users`.`id` DESC LIMIT 10
2019-10-02 by Antonia Horincar

rails: run system tests and normal tests with one command

rails test test:system does only execute unit tests but not the system tests… rails test:system test on the other hand does. Obviously…

see: https://stackoverflow.com/questions/45798635/rails-5-1-run-system-tests-and-normal-tests-with-one-command

2019-09-25 by Philipp Koster

Explicitly mount files with docker-compose

When mounting files in docker compose, like this:

volumes:
  - ./file-to-mount:/target/file-to-mount

an empty directory is created inside the container, if the file-to-mount does not exist! This leads to annoying debug sessions…

One can use the following syntax (with docker-compose 3.4), to mount a file more explicitly:

    volumes:
      - type: bind
        source: ./file-to-mount
        target: /target/file-to-mount

Now, when the file does not exists, it is not possible to start the container.

invalid mount config for type "bind": bind source path does not exist...
2019-09-18 by Philipp Koster

Run command line scripts from within Rake tasks

My usual approach when writing Rake tasks is to import a library and then use its API:

require_relative '../slides'

namspace :slides do
  desc 'Create an empty slideshow'
  task :new do
    Slides.new.write_to_disk
  end
end

Sometimes that is impractical: the API is not public, or you need to invoke a standalone script which only has a command line interface.

I found out Rake implements a ruby method which lets you invoke the ruby program directly:

task :new do
  ruby 'create_slideshow.rb'
  puts 'Created a new slideshow.'
end

There is also a sh method, which allows you to run system commands. Make sure to use the multiple argument version and avoid passing it unfiltered user input.

2019-09-11 by Dimiter Petrov

Install mysql gem on Mac OS X

According to this Gist.

brew install mysql
brew install openssl
gem install mysql2 -v '0.5.2' -- --with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include
2019-09-05 by Andy Pfister

Step through migrations in Rails

tl;dr db:forward is the opposite of db:rollback

bin/rails db:migrate

runs all pending migrations.

If you want to migrate to a specific DB version, you can use

bin/rails db:migrate VERSION=20190730123456

which is rather cumbersome, especially if you only want to run one migration. Therefore you can use

bin/rails db:forward

You can combine it with variable STEP to execute multiple migrations.

bin/rails db:forward STEP=5
2019-08-02 by Mario Schüttel

rubocop-rails

rubocop 0.72.0 removes all Rails cops, since they “[…] want RuboCop to be focused just on Ruby […]” (and I agree with them), see PR #5976.

In order to use the Rails cops after rubocop 0.72.0, we need to add rubocop-rails gem and require it as a dependency in .rubocop.yml:

require:
  - rubocop-rails
2019-07-29 by Mario Schüttel

Enumerable#grep

Ruby enumerables respond to grep. You can use it to quickly filter a collection with a regular expression.

['Marta', 'Mario', 'Bill'].grep(/Ma/)
# => ['Marta', 'Mario']
2019-07-12 by Dimiter Petrov

Update nested maps in Elixir

Being a functional programming language, Elixir is a bit different from other languages when it comes to update a nested data structure.

For example, in javascript we could do:

data = {
  inner: {
    one: {
      a: 1
    },
    two: {
      b: 45
    }
  }
}

data.inner.one.a = 2

In Elixir you have to build a new map with the updated information, for example:

data = %{
  inner: %{
    one: %{
      a: 1
    },
    two: %{
      b: 45
    }
  }
}

new_one = %{data.inner.one | a: 2}
new_inner = %{data.inner | one: new_one}
new_data = %{data | inner: new_inner}

which is not very handy.

In other functional languages like Haskell, there are libraries like Lenses that aims to solve the problem. In Elixir the kernel have an put_in function that acts in a similar way:

data = put_in(data, [:inner, :one, :a], 2)

You can find other similar functions in the Kernel documentation

2019-06-13 by Tiziano Puppi

The query function in Ecto Repo (Elixir)

There is a hidden function in Ecto which is the function query in the Repo module.

This is a wrapper around the Ecto.Adapters.SQL.query and it is injected in the Repo module of your application. It can be called in this way:

MyApp.Repo.query("SELECT * FROM mytable")

This function can also take an array of query parameters like:

MyApp.Repo.query("""                                           
SELECT * FROM mytable
WHERE id = $1
""", [42])

This is quite handy when you need to debug in production, and there is no database client available.

2019-06-07 by Tiziano Puppi

Union, Difference and Intersect with Ruby Arrays

Union

> [:a, :b, :c].union([:b, :c, :d])
 => [:a, :b, :c, :d]
# or 
> [:a, :b, :c] | [:b, :c, :d]
 => [:a, :b, :c, :d]

“Union all” / Concat

[:a, :b].concat([:b, :c])
 => [:a, :b, :b, :c]
# or
[:a, :b] + [:b, :c]
 => [:a, :b, :b, :c]

Difference

> [:a, :b, :c].difference([:b, :c, :d])
 => [:a]
# or
[:a, :b, :c] - [:b, :c, :d]
 => [:a]

Intersect

> [:a, :b, :c] & [:b, :c, :d]
 => [:b, :c]
2019-06-07 by Mario Schüttel

The sample output HTML element

There is an HTML element called <samp> meant for representing computer program output. The specification document has this humorous example:

<p>The computer said <samp>Too much cheese in tray
two</samp> but I didn't know what that meant.</p>