Git: How to rebase your feature branch from one branch to another
In a nutshell: Use git rebase --onto target-branch source-commit
-
target-branch
means "branch you want to be based on" -
source-commit
means "commit before your first feature commit"
Let's say my-feature-branch
is based on master
and we want it to be based on production
. Consider this history:
%%{init: { 'gitGraph': {'showCommitLabel': true, 'mainBranchName': 'production'}} }%%
gitGraph
commit id: "1"
commit id: "2"
branch master
commit id: "3"
commit id: "4"
branch my-feature...
Touch devices don't have mouseover events
It might sound trivial, but there is no such thing as a "hover" or "mouseover" state on touch devices. If your application is supposed to work on iPads, smartphones, etc., don't hide information behind a tooltip, and don't make controls appear when hovering over another element.
Generally, things that happen/appear when you hover an element should do the same when you click the element.
Chromedriver issue #4550 breaks the user agent for device emulation via device name
Newest versions of Chromedriver breaks the user agent for device emulation via device name. In previous versions the user agent of the emulated device was set. In the newest versions the user agent differs from the emulated device.
- Version Chrome: 116.0.5845.110
- Version Chromedriver: 116.0.5845.96
- Bug: https://bugs.chromium.org/p/chromedriver/issues/detail?id=4550&q=userAgent&can=2
- Setting: https://chromedriver.chromium.org/capabilities
In Capybara an affected config looks like following:
Capybara.register_driver :mobi...
Capybara: How to find the focused element
Capybara allows you to filter elements that are focused.
page.find(:fillable_field, focused: true) # Filtering only fillable inputs for performance reasons
page.find(:xpath, '//*', focused: true) # Filter all fields
Legacy approach
In older version, it was possible to use the :focus
pseudo-class. This seems not to work in newer versions anymore.
find(':focus')
Web Components Accessibility FAQ
In the linked page, Manuel Matuzović offers an FAQ regarding web components, and their accessibility in particular.
At time of writing this card, the post is still work in progress and will expand over time.
I can also recommend his blog in general.
Postgres in Alpine docker container: sorting order might differ
In CI test runs I noticed that string sorting order changed after switching from a debian-based PostgreSQL docker image to one that is based on Alpine Linux.
Debian image sorting: bar Bar foo Foo
Alpine image sorting: Bar Foo bar foo
Explanation
Alpine Linux is a very slim linux distribution that results in small docker image sizes (roughly 100MB instead of 150MB), so it's a popular choice. However, it does not have all comman locales installed and does not use all locales that a user installs by default.
Postgres orders string co...
Minifying object properties in JavaScript files
An introduction to mangling
When you minify ("compress", "optimize") your JavaScript for production, the names of your functions and variables will be renamed for brevity. This process is often called mangling.
E.g. if this is your source code:
function function1() {
function2()
}
After mangling it would look like this:
function a() {
b()
}
Object properties are not mangled by default
Minfiers never mangle properties by default, as this can be an unsafe transformation. This leads to larger file sizes if...
Debugging SPF records
While debugging a SPF record I found spf-record.de to be very helpful.
- it lists all IPs that are covered by the SPF record
- shows syntax errors
- helps you debugging errors like DNS lookup limit reached
- it also lets you test a new SPF strings before applying it. This can save you time as you don't have to loop with operations
Also the advanced check at vamsoft.com has a very good interface to test new SPF policies.
HTTP 302 redirects for PATCH or DELETE will not redirect with GET
A HTTP 302 Found
redirect to PATCH
and DELETE
requests will be followed with PATCH
or DELETE
. Redirect responses to GET
and POST
will be followed with a GET
. The Rails form_for
helper will use a workaround to send POST
requests with a _method
param to avoid this issue for PATCH
/DELETE
.
If you make requests yourself, watch out for the following behavior.
When you make an AJAX request PATCH /foo
and the /foo
action redirects to /bar
, browsers will request PATCH /bar
. You probably expected the second requ...
What's so hard about PDF text extraction?
There is a common view that extracting text from a PDF document should not be too difficult. After all, the text is right there in front of our eyes and humans consume PDF content all the time with great success. Why would it be difficult to automatically extract the text data?
Turns out, much how working with human names is difficult due to numerous edge cases and incorrect assumptions, working with PDFs is difficult due to the extreme flexibility given by the PDF format.
Node: How to run a globally installed package with npx
You can tell npm
to install a package globally with npm -g install @puppeteer/browsers
. However, it seems that its not possible that npx
can run commands from global packages without referencing the global package path.
Example
Installing @puppeteer/browsers
globally:
$ npm -g install @puppeteer/browsers
The globally installed package @puppeteer/browsers
can not be access via npx
:
$ npx --no-install @puppeteer/browsers
npm ERR! canceled # Error message when package is not installed
But it is installed g...
RSpec: How to write isolated specs with cookies
Background
Rails offers several methods to manage three types of different cookies along with a session storage for cookies. These are normal, signed and encrypted cookies.
By following the happy path of testing a web application, that is only the main use-case is tested as a integration test and the rest as isolated (more unit ...
Rails: Kill spring with fire
To ensure Spring is not running:
bin/spring stop
pkill -f spring
To prevent Spring from starting again:
export DISABLE_SPRING=1
Devise: Invalidating all sessions for a user
Background information about session storage in Rails
Rails has a default mechanism to store the session in the CookieStore
. This is a cookie which holds the entire user session hash in the browser. This cookie is serialized, encoded with base64, and signed.
How Devise handles authentication
Devise uses this CookieStore
. To track a users session, a salt is stored in the session ...
NVM: How to automatically switch version when changing directories
The Node Version Manager allows installing multiple NodeJS versions and switching between them.
By default, it does not automatically switch versions when entering a directory that holds a .nvmrc
file.
The project's readme document offers a bash function which calls nvm use
after each cd
. In fact, it replaces cd
in your bash.
I did not want to do that, but instead use the $PROMPT_COMMAND
feature. So here is my take on it.
Note that it is much shorter, it probably does a f...
Scrum: Online Planning Poker
If you are using scrum in a project you might be familiar with planning poker, a playful way to agree on story estimates.
PoinZ is an online planning poker app for just that. It's easy to use and does not require registration.
How to transition the height of elements with unknown/auto height
If you want to collapse/expand elements with dynamic content (and thus unknown height), you can not transition between height: 0
and height: auto
.
Doing it properly, with modern CSS features
In the past, you might have resorted to bulky JavaScript solutions or CSS hacks like transitioning between max-height: 0
and max-height: 9999px
. All of them were awkward and/or have several edge cases.
With modern CSS, there is actually a way to do it properly:
Just use a display: grid
container which transitions its grid row height betwe...
How to prevent a 1fr grid column overflow
TL;DR:
Grid elements have
min-width: auto
in a1fr
column, which may lead to overflows. Withminmax(0, $width)
you can reset the min-width.
Say you have a simple grid layout:
.container
.first-item
.second-item
.third-item
.container
display: grid
grid-template-columns: 100px 1fr 100px
Your expectation is now that
- the first item will be located on the left hand side with a fixed width of 100px
- the third item will be located on the right hand side, also with a width of 100px
- ...
Use -webkit-line-clamp to natively truncate long (multi-line) texts with an ellipsis
Note: You won't need this for single lines of text. In this case it is better to just use the text-overflow
property: Use CSS "text-overflow" to truncate long texts
You can use -webkit-line-clamp
in your CSS/SASS to natively render an ellipsis (...
) after a specific amount of lines for a multi-line text in your HTML.
Earlier, it was necessary to implement JavaScript solutions like Superclamp.js to enable this because the browser support has been rather limited...
E-mail deliverability
When your application is open for public sign up and sends out transactional e-mails to a large number of users, e-mail deliverability becomes an issue.
E-mail providers work hard to eliminate spam and have put in place relatively tight checks what kinds of emails they will accept, and from whom. To that end we use tools like mail-tester.com to make our mails as acceptable as possible. Unfortunately, there will always be providers that reject our e-mails for some reason or other, sometimes outside of our control.
For exa...
How Rails chooses error pages (404, 500, ...) for exceptions
When your controller action raises an unhandled exception, Rails will look at the exception's class
and choose an appropriate HTTP status code and error page for the response.
For instance, an ActiveRecord::RecordNotFound
will cause Rails to render a red "The page you were looking for doesn't exist" with a status code of "404" (not found).
The mapping from exception classes to error types is a hash in Rails.configuration.action_dispatch.rescue_responses
. The...
Sentry: Different ways of deferring notifications for an issue
We use Sentry to be informed about different kinds of issues. One of the key features is that you are not getting spammed if many errors of the same kind occur in a small timespan.
If an issue pops up the usual workflow is to fix the code and mark the issue as "resolved" in Sentry. Only new or resolved issues trigger another email notification when they are proxied through Sentry.
This workflow does not fit well for issues we cannot fix, e.g. when consuming an external API that is sometimes down. In such cases you ...
Useful filtering options of git log
Git log
offers useful options for filtering. This card provides a short overview.
By message
Only commits that include a specific string in their commit message
git log --grep="tracker id"
By file
Only commits that introduced changes to a specific file
git log -- foo.rb bar.rb
Note
In case the file was renamed or moved the
--follow
option can be helpful
git log --follow -- foo.rb
By content
If you want to know when a specific line of code was added in the project
git log -S"def function_name"
By range
...
A non-weird replacement for grouped_collection_select
Rails comes with grouped_collection_select
that appears to be useful, but isn't.
As an alternative, consider the flat_grouped_collection_select
found below. It takes a third argument that extracts the group from each element in the collection:
= form.flat_grouped_collection_select :user_id, users, :department, :id, :full_name
Here is the monkey-patch:
class ActionView::Helpers::FormBuilder
def flat_grouped_collection_selec...