Balance your texts today with text-wrap: balance
So you have a heading that is just barely wider than the container it should fit into, and it wraps a single word to a new line and it's not really pretty?
Cry no more, for you can use text-wrap: balance
today to fix that. At least in some browsers.
When browsers encounter a text-wrapping element with text-wrap: balance
style, they will try breaking to a new line sooner, if it balances out the width of lines.
text-wrap: unset |
text-wrap: balance |
---|---|

- avoids "magic numbers" (don't say e.g. ...
Ruby: alias_method conflicting with prepend
alias_method
makes a copy of a method. This works fine until the same method is overridden using prepend
. If the prepend
is executed after alias_method
, you'll either see an infinite loop, or loose the prepended functionality.
Solution
Your options are:
- Ensure
prepend
happens beforealias_method
- If you can control the
alias_method
invocation: rewrite to the modern & betterprepend
- If you can only control the
prepend
invocation: rewrite to the legacyalias_method
Git: Splitting up changes into several commits
Splitting up commits makes the process of reviewing often easier, since you can create several merge requests or review every commit one by one.
So when you find out that you have portions of the code that you initially didn't intend to change or when you do some refactoring along the current changes, you can use one of the following processes to split up the changes into several commits in a logical order:
#1 Splitting up the last n commits into m commits
#2 Adding changes to a previous commit
2.1 While adding new changes
2.2 S...
Best practice: How to manage versions in a package.json
It most cases it's not necessary to add a version constraint next to your packages in the package.json
. Since all versions are saved in a lockfile, everyone running yarn install
will get exactly the same versions. Yarn saves this lockfile as yarn.lock
and npm as package-lock.json
.
There are some exceptions, where you can consider adding a version constraint to the package.json
:
- You are not checking the lockfile into version control (not recommended)
- A specific package has a bug in a more recent version
- You want to ensure no...
Best practice: How to manage versions in a Gemfile
It most cases it's not necessary to add a version constraint next to your gems in the Gemfile
. Since all versions are saved in the Gemfile.lock
, everyone running bundle install
will get exactly the same versions.
There are some exceptions, where you can consider adding a version constrain to the Gemfile
:
- You are not checking in the
Gemfile.lock
into the version control (not recommended) - A specific gem has a bug in a more recent version (adding a comment for the reason is highly recommended)
- You want to ensure no one upgrade...
RSpec 3 argument constraints use weak equality
If you expect method calls in RSpec 3, be aware that the argument matchers use very liberal equality rules (more like ===
instead of ==
).
For example:
expect(subject).to receive(:foo).with(MyClass)
subject.foo(MyClass) # satisfies the expectation
subject.foo(MyClass.new) # also satisfies the expectation
expect(subject).to receive(:bar).with(/regex/)
subject.bar(/regex/) # satisfies the expectation
subject.bar('regex') # also satisfies the expectation
This is usually not an issue, except when your method ...
Rails < 5: How to get after_commit callbacks fired in tests
If you use transactional_fixtures
or the database_cleaner gem with strategy :transaction
, after_commit
callbacks will not be fired in your tests.
Rails 5+
Rails 5 has a fix for this issue and no further action is needed.
Rails 3, Rails 4
Add the gem test_after_commit to your test
group in the Gemfile and you are done. You don't need to change the database strategy to deletion
(wh...
ActiveRecord: Creating many records works faster in a transaction
When you need to insert many records into the same table, performance may become an issue.
What you can do to save time is to open a transaction and save multiple records within that transaction:
transaction do
500.times { Model.create! }
end
Although you will still trigger 500 INSERT
statements, they will complete considerably faster.
When I tried it out with a simple model and 500 iterations, the loop completed in 1.5 seconds vs. 6 seconds without a transaction.
Alternative
Another fast way to insert many ...
Local deployment after pipeline succeeds
If you have a fully functional CI pipeline but no CD, you might find yourself frequently waiting for CI (with "merge after pipeline succeeds") just to perform the deployment.
The following command waits for the next commit that lands on the current branch (should be main
or similar) and proceeds to deploy staging afterwards:
alias await-deployment='watch -g git pull && bundle exec cap staging deploy'
Note
Use at your own risk.
You could be deploying code from someone else that was pushed to the same branch in the meantime.
How to configure case insensitive git output
Git commands like diff
use the less
binary for their output representation.
I often find myself searching for strings like todo
, then switching to the case-insensitive mode (-i
) and re-doing my search.
Today I figured out that you can configure git to show case insensitive diffs every time:
git config --global core.pager 'less -i'
Geordi 9.6.0 released: new "did you know?" feature
Geordi will now suggest related commands and options (hand-picked). If a command has suggestions, a single suggestion is printed with a 10% probability after a successful command.
Find Where a Rake Task is Defined
You can use rake --where task
to find the source location that defines task
:
bundle exec rake --where assets:precompile
rake assets:precompile /home/henning/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/precompiled_assets-0.2.1/lib/precompiled_assets/tasks/assets.rake:5:in `block in <main>'
Vim: Simple way to edit several lines at once at the same cursor position
Within Vim do the following:
- Move cursor to the first starting line where you want to start editing
-
ctrl + v
to enter select mode to select all characters in one column - Move the cursor vertically down until you selected the last line
-
shift + i
to got into "multiple" insert mode - Do all the required editings
- Use the
ESC
-character exit insert mode - Press
ESC
-character to apply all changes
Hint
This does not work with deleting and editing at once
- If you first want to delete the content, can also use the select mode ...
Capo: putting <head> content into the right order
How you order elements in the <head> can have an effect on the (perceived) performance of the page.
This script helps you identify which elements are out of order.
Also available as a Chrome Extension. It shows the actual order of head elements, and suggests an optimal order for page performance.
Linux: How to make a terminal window title reflect the current path
By default, your terminal emulator (Gnome Terminal, Terminator, etc.) sets some kind of window title to reflect the shell type you are running (e.g. /bin/bash
).
This is most often not too helpful, but you can change that from your shell.
To set a specific title, print an escape sequence like this:
echo -en "\033]0;Hello\a"
You can easily include the current path:
echo -en "\033]0;$(pwd)\a"
Or, to replace your home directory's part with a tilde:
echo -en "\033]0;$(pwd | sed -e "s;^$HOME;~;")\a"
Or,...
About Ruby's conversion method pairs
Ruby has a set of methods to convert an object to another representation. Most of them come in explicit and implicit flavor.
explicit | implicit |
---|---|
to_a |
to_ary |
to_h |
to_hash |
to_s |
to_str |
to_i |
to_int |
There may be even more.
Don't name your methods like the implicit version (most prominently to_hash
) but the like the explicit one.
Explicit conversion
Explicit conversion happens when requesting it, e.g. with the splat opera...
Git diff: Deemphasizing code that was only moved around
In long diffs, it can become impossible to spot small changes in larger blocks of moved code. This may be either a method that was moved from the top to the bottom of a file, or a long test file that was split in many.
Fortunately, Git offers a special highlighting mode that directs the reader's attention to relevant code parts:
git diff --color-moved=dimmed-zebra
It will dim lines that were moved around without changes, and highlight changed lines.
To easily use dimmed-zebra mode, configure an alias:
# ~/.gitconfig
[alias]
...
Testing shared traits or modules without repeating yourself
When two classes implement the same behavior (methods, callbacks, etc.), you should extract that behavior into a trait or module. This card describes how to test that extracted behavior without repeating yourself.
Note that the examples below use Modularity traits to extract shared behavior. This is simply because we like to do it that way at makandra. The same techniques apply for modules and overriding self.included
.
Example
---...
How to: Run bundle install in parallel
You can run bundle install in parallel. This might be helpful for development, where you often install many new gems when switching between projects.
- Find out the number of processors you have:
lscpu
- Set the config in your
~/.bundle/config
globally (replace8
with your number of proccessors):
bundle config jobs 8
Note
If you suspect parallel execution for bundling issues, you can try serially with
bundle install --jobs 1
.
ss: How to show listening ports
Note
netstat has mostly been superseeded by its more modern rewrite
ss
which nowadays comes pre-installed rather than netstat.
The most common options (especially all that are mentioned in this card) work the same way as they did with netstat
Sometimes it's necessary for you to check which ports are in use on your local machine and which process is using it. To list this information you can use the following command (which is pretty easy to memorize for Germans 🌷):
sudo ss -tulpn
-
t
: tcp -
u
: udp -
l
: listening p...
Raising JavaScript errors in Ruby E2E tests (RSpec, Cucumber)
A JavaScript error in an E2E test with Selenium will not cause your test to fail. This may cause you to miss errors in your frontend code.
Using the BrowserConsole
helper below you can check your browser's error console from your E2E tests.
The following will raise BrowserConsole::ErrorsPresent
if there is an error on the browser console:
BrowserConsole.assert_no_errors!
Ignoring errors
You can ignore errors by their exact message:
BrowserConsole.ignore('Browser is burning')
You can ignore errors with me...
Don't assert exceptions in feature specs
As we are slowly switching from Cucumber scenarios to RSpec feature specs, you might be tempted to write assertions like this one:
feature 'authorization for cards management' do
let(:guest_user) { create(:user, :guest) }
scenario "rejects guest users from adding new cards", js: true do
sign_in guest_user
expect { visit new_cards_path }.to raise_error(Consul::Powerless)
end
end
While this might work under certain circumstances¹, there is a good chance you'll see two exceptions when running this single spec:
- ...
How to pretty print all values in a Redis database
With this Ruby script you can print all values in a Redis database to your console (derived from this bash script).
Note: Do not run this command in production. This is for debugging purposes only.
def pretty_print_redis(redis)
redis.keys.each_with_object({}) do |key, hash|
type = redis.type(key)
hash[key] = case type
when 'string'
redis.get(key)
when 'hash'
redis.hgetall(key)
when 'list'
redis.lrange(key, 0, -1)
when 'set'
redis.smembers(...