Timecop is a great gem to set the current time in tests. However, it is easy to introduce flakyness to your test suite when you forget to reset the time after the test.
This might be the case if:
Often you only notice these kinds of errors in rare cases when tests are executed in a particular order.
A way to avoid this is by using block notation (`Timecop.travel(...) ...
In a Jasmine spec you want to spy on a function that is imported by the code under test. This card explores various methods to achieve this.
We are going to use the same example to demonstrate the different approaches of mocking an imported function.
We have a module 'lib'
that exports a function hello()
:
// lib.js
function hello() {
console.log("hi world")
}
export hello
We have a second module 'client'
that exports a function helloTwice()
. All this does is call hello()
...
We usually rely on VCR and WebMock to prevent any real network connection when running our unit tests.
This is not entirely true: They are both limited to a set of HTTP libraries listed below (as of 2022). Direct calls to Kernel#open
or OpenURI#open_uri
are not mocked and will trigger real network requests even in tests. This might bite you e.g. in [older versions of CarrierWave](https://github.com/carrierwaveuploader/carrierwave/blob/0.11-stable/lib/carrierwave/upl...
By default subscript (<sub></sub>
) and superscript (<sup></sup>
) tags are styled with vertical-align: sub
, respectively vertical-align: super
by most browsers.
However, without adaptations, this will probably break your line-heights.
A common suggestion is to style those two tags accordingly:
sup, sub {
vertical-align: baseline;
position: relative;
top: -0.4em; /* can be adapted according to preferences */
}
sub {
...
You have some SVG files you want to use as icons on your website. How would you embed them?
Common options are:
<img src='path-to-icon.svg'>
<svg>$ICON</svg>
background-image: url(path-to-icon.svg)
or even background-image: url(data:$ICON)
.All of these have drawbacks:
background-image
do not allow to recolor the image using CSS.<svg>
are unnecessary work for the server and are...In esbuild, you usually import other files using relative paths:
import './some-related-module'
import `../../utils/some-utility-module`
import `../../../css/some-css.sass`
This is totally fine if you import closely related files, but a bit clunky when you're trying to import some "global" module, like a utility module. When moving a file, your imports also need to change.
To get around this, esbuild support a mechanism first introduced in TypeScript called "path aliases". It works like this:
First, you create a file called `js...
Jasmine specs for the frontend often need some DOM elements to work with. Because creating them is such a common task, we should have an efficient way to do it.
Let's say I need this HTML structure:
<ul type="square">
<li>item 1</li>
<li>item 2</li>
</ul>
This card compares various approaches to fabricating DOM elements for testing.
While you can use standard DOM functions to individually create and append elements, this is extremely verbose:
let list = document.createElement('...
Jasmine specs that work with DOM elements often leave elements in the DOM after they're done. This will leak test-local DOM state to subsequent tests.
For example, this test creates a <spoiler-text>
element, runs some expectations, and then forgets to remove it from the DOM:
describe('<spoiler-text>', function() {
it ('hides the secret until clicked', function() {
let element = document.createElement('spoiler-text')
element.secret = 'The butler did it'
document.body.appendChild(element)
...
tl;dr
The Chrome DevTools are a neat collection of tools for the daily work as a web developer. If you're lucky, you'll maybe find some handy stuff in here.
You can use ETags to allow clients to use cached responses, if your application would send the same contents as before.
Besides what "actually" defines your response's contents, your application probably also considers "global" conditions, like which user is signed in:
class ApplicationController < ActionController::Base
etag { current_user&.id }
etag { current_user&.updated_at }
end
Under the hood, Rails generates an ETag header value like W/"f14ce3710a2a3187802cadc7e0c8ea99"
. In doing so, all objects from that etagge...
tl;dr
git checkout
is the swiss army of git commands. If you prefer a semantically more meaningful command for restoring tasks, usegit restore
instead.With this command you can ...
- ... do unstaging -
git restore --staged
- ... discard staged changes -
git restore --staged --worktree
- ... discard unstaged changes -
git restore
- ... restore deleted files -
git restore
- ... restore historic versions -
git restore --source
- ... recreate merge conflicts -
git restore --merge
- ... specifiy...
You have uncommited changes (you can always check by using git status
), which you want to discard.
Now there are several options to discard these depending on your exact situation.
The headlines will differentiate the cases whether the files are staged or unstaged.
git reset --hard
git stash
will add the changes to the stash, reverting the local repository to HE...
tl;dr
In RubyMine you can use find and replace with capture groups
(.*?)
and backreferences$1
(if you have several groups:$[Capture-Group ID]
).
Named captures(?<text>.*)
are also supported.
If you want to replace double quotes with single quotes, replacing every "
with a '
is prone to errors. Regular expressions can help you out here.
.*
icon next to the "find" field).To allow HTTP 304 responses, Rails offers the fresh_when
method for controllers.
The most common way is to pass an ActiveRecord instance or scope, and fresh_when
will set fitting E-Tag
and Last-Modified
headers for you. For scopes, an extra query is sent to the database.
fresh_when @users
If you do not want that magic to happen, e.g. because your scope is expens...
When you build a JSON API you need to come up with a style to represent attributes, pagination, errors or including associated objects. Instead of reinventing the wheel, you may reuse successful API designs.
JSON:API specifies common features found in most JSON APIs, like pagination, ordering and nested resources. The spec looks very similar to how one would build an API with Rails and uses similar patterns. Even if you don't plan on supporting the whole spec, it can still make sense to know how th...
When working with feature branches, stale branches pile up over time. It's best to remove them right after merge, locally and on the remote, but it is a little tedious: you need to remember it, and perform the few steps manually each time.
Enter Git hooks. The folks at Liquid Light have built a little post-merge hook that will delete a feature branch on confirmation....
Recently we detected a memory leak in one of our applications. Hunting it down, we found that the memory leak was located in Rails' #prepend_view_path
. It occurs when the instance method prepend_view_path
is called in each request, which is a common thing in a multi-tenant application.
On top of leaking memory, it also causes a performance hit, since templates rendered using the prepended view path will not be cached and compiled anew on each requqest.
This is not a new memory leak. It was [first reported in in 2014](https://github.com...
It might sometimes be useful to check whether your Rails application accesses the file system unnecessarily, for example if your file system access is slow because it goes over the network.
The culprit might be a library like carrierwave that checks file existence or modification times, whereas your application could determine all this from your database.
One option it to use strace for this, which logs all system calls performed by a process.
To do this, start your rails server using something like
DISA...
The gemspec for gems allows to add metadata to your gem, some of which have a special meaning and are helpful for users.
You can provide links to your Github bugtracker or changelog file that are then used on the rubygems page of your gem (in the sidebar, e.g. see gem page of consul).
Here are some keys that should be filled:
Gem::Specification.new do |s|
s.name = 'my-gem'
s.homepage = 'https://github.com/makandra/my-gem'
s.metadata = {
'source_code_uri' => s.homepage,
'bug_tracker...
This card explains how to generate an entity relationship diagram for your Rails application.
We also show how to limit your ERD to a subset of models, e.g. models inside a namespace.
Sometimes we write plain SQL queries in migrations so we don't have to mock ActiveRecord classes. These two migrations do the same:
class Migration1 < ActiveRecord::Migration[5.2]
class User < ActiveRecord::Base; end
def up
add_column :users, :trashed, :boolean
User.update_all(trashed: false)
end
end
class Migration2 < ActiveRecord::Migration[5.2]
def up
add_column :users, :trashed, :boolean
update("UPDATE users SET trashed = #{quoted_false}")
end
end
The plain SQL migration is less code, but h...
You want to deploy new features but the latest commits are not ready for production? Then use git merge master~n
to skip the n-last commits.
Tip
A big advantage of merging vs. cherry-picking is that cherry-picking will create copies of all picked commits. When you eventually do merge the branch after cherry-picking, you will have duplicate commit messages in your history.
It's time for a production deployment!
git log --pretty=format:"%h - %s" --reverse origin/production..origin/master
0e6ab39f - Feature A
6396...
Sometimes you need to access a dev server running on localhost from another machine that is not part of the same network. Maybe you want to use your phone to test a web page, but are only in a guest WiFi. In the past, we often used some port forwarding or other techniques to expose the service to the internet.
Enter ngrok, a command line tool that gives you an on-the-fly internet...
Since Rails 6.1, if we use where.not
with multiple attributes, it applies logical NAND (NOT(A) OR NOT(B)) instead of NOR (NOT(A) AND NOT(B)). If you do not take care, this change will increase the matched set.
"Don't send newsletters neither to admins nor to trashed users!" becomes "Don't send newsletters to trashed admins".
User.where.not(role: 'admin', trashed: true)
# Before Rails 6.1, with NOR
=> "SELECT "users".* FROM "users" WHERE "users"."role" != 'admin' AND "users"."trashed" != TRUE"
# Equivale...