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()
}
Minfiers never mangle properties by default, as this can be an unsafe transformation. This leads to larger file sizes if...
While debugging a SPF record I found spf-record.de to be very helpful.
Also the advanced check at vamsoft.com has a very good interface to test new SPF policies.
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...
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.
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.
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...
Added information that verifying doubles have some limited usages with dynamically defined methods along with some advice on how to handle this.
This includes a link to the documentation that shows several ways on how this can be addressed and a link on how to disable verifying doubles if a simpler approach is necessary.
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 ...
To ensure Spring is not running:
bin/spring stop
pkill -f spring
To prevent Spring from starting again:
export DISABLE_SPRING=1
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.
Devise uses this CookieStore
. To track a users session, a salt is stored in the session ...
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...
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.
If you want to collapse/expand elements with dynamic content (and thus unknown height), you can not transition between height: 0
and height: auto
.
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...
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
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...
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...
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...
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 ...
Git log
offers useful options for filtering. This card provides a short overview.
Only commits that include a specific string in their commit message
git log --grep="tracker id"
Only commits that introduced changes to a specific file
git log -- foo.rb bar.rb
If you want to know when a specific line of code was added in the project
git log -S"def function_name"
If you want to know which commits have been added between two commits.
git log base_branch..compare_branch
will s...
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...
In general, the tracker should always be the definitive source of truth of what needs to be done as part of a project. If you identify a task that needs to be done, you should create a story. If you learn something that contradicts an existing story, change it.
The tracker can contain two types of stories: Developer stories, and non-developer stories.
Non-developer stories should be clearly marked. They usually belong to the PM (or maybe people from the operations team). Those story can take all forms, could just...
capybara_element['attribute_name']
allows accessing an element's attributes in Capybara.
A few examples:
find('#my_element')['class']
# => "first-class second-class"
find('#my_input')['placeholder']
# => "My placeholder value"
find('a#example-link')['href']
# => "http://example.com"
find('#my_element')['missing_attribute']
# => nil
Sometimes you'll find yourself with a set of tasks that require similar code for different models. For example, if you start working at a new application that allows CRUDing pears and apples, each commit might look similar to this:
commit 41e3adef10950b324ae09e308f632bef0dee3f87 (HEAD -> ml/add-apples-12345)
Author: Michael Leimstaedtner <michael.leimstaedtner@acme.com>
Date: Fri Aug 11 09:42:34 2023 +0200
Add Apples as a new fruit
diff --git a/app/models/apple.rb b/app/models/apple.rb
new file mode 100644
index 0000000..a51...
Suppose you want to implement a publish/subscribe pattern in your Frontend application to react to data changes and events. First, you might be looking for an event emitter library.
Today I learned that vanilla JavaScript comes with a native event emitter, which I've been indirectly using forever. There's no need for extra code!
const emitter = new EventTarget()
emitter.addEventListener('YOLO', () => {
console.log('YOLO');
})
// invoke attached event listeners
emitter.dispatchEvent(new Event('YOLO'));
First find the reference for the entry you want through looking at the stash:
$ git stash list
stash@{0}: WIP on feature/foo
stash@{1}: WIP on feature/bar
stash@{2}: WIP on fix/baz
Now you can simply use that reference, but curly braces must be escaped:
git stash pop stash@\{1\}
or quoted:
git stash apply "stash@{1}"