If you need a sample video with certain properties for a test you can create one using ffmpeg.
You might want a very low bitrate file to speed up processing in your test. (e.g. you only care about the length, then you can create a video with a very low resolution and framerate)
Create a 21s video with 1fps and 10x10 resolution:
ffmpeg -t 21 -s 10x10 -r 1 -f rawvideo -pix_fmt rgb24 -i /dev/zero sample_21_seconds.mp4
Option | Explanation |
---|---|
-t 21 |
set the length to 21s |
-s 10x10 |
set the resolution the 10 by 10 p... |
This is an story checklist I use to work on stories. For this purpose I extracted several cards related to the makandra process and ported them into a check list and refined that over time a little bit.
This task list is divded by the Gate keeping process in the following steps:
1. Starting a new feature
2. Working on the story
3. Finishing a feature
4. After Review
Here are ...
Rails partials have a lot of "hidden" features and this card describes some non-obvious usages of Rails Partials.
The most basic way to render a partial:
render partial: 'partial'
This will render a _partial.html.erb
file. Notice how all partials need to be prefixed with _.
It's possible to define local variables that are only defined in the partial template.
# _weather.html.erb
<h1>The weather is <%= condition %></h1>
# index.html.erb
render partial: 'weather', locals: { condition: ...
Not all email clients support external images in all situations, e.g. an image within a link. In some cases, a viable workaround is to turn your images into inline attachments.
Note
Rails provides a simple mechanism to achieve this:
This documentation makes it look like you have to care about these attachments in two places. You have to create the attachment in t...
Carrierwave's BaseUploader
can have some validations that you can use by overriding a certain method, which's expected name is hard coded. A popular example is extension_allowlist
, which returns an array of strings and let's you only upload files that have a filename with an extension that matches an entry in that array. Another useful validation can be size_range
, which gives you a little bit of control over how your storage gets polluted.
This is often good enough, but some times you need to validate special cases.
Since Rails 7 you are able to encrypt database information with Active Record. Using Active Record Encryption will store an attribute as string in the database. And uses JSON for serializing the encrypted attribute.
Example:
p
: Payloadh
: Headersiv
: Initialization Vectorat
: Authentication Tag{ "p": "n7J0/ol+a7DRMeaE", "h": { "iv": "DXZMDWUKfp3bg/Yu", "at": "X1/YjMHbHD4talgF9dt61A=="} }
Note this before encrypting attributes with Active Record:
...
Sometimes I ran across a GitHub merge request of a gem where it was not completely obvious in which version the change was released. This might be the case for a bugfix PR that you want to add to your project.
Git can help you to find the next git tag that was set in the branch. This usually has the name of the version in it (as the rake release
task automatically creates a git tag during release).
git name-rev --tags <commit ref>
Note
The more commonly used
git describe
command will return the last tag before a c...
Rails includes milliseconds in Time
/ DateTime
objects when rendering them as JSON:
JSON.parse(User.last.to_json)['created_at']
#=> "2001-01-01T00:00:00.000+00:00"
In RSpec you might want to use .to_json
instead of .iso8601
to use the build-in eq
matcher:
it 'returns the created at attribute of a user' do
get '/users/1'
expect(JSON.parse(response.body)['created_at']).to eq(Time.parse('2001-01-01').to_json)
end
Otherwise the strings do not match:
DateTime.parse('2001-01-01').to_s (will defa...
Sometimes, the rails dev server doesn't terminate properly. This can for example happen when the dev server runs in a RubyMine terminal.
When this happens, the old dev server blocks port 3000, so when you try to start a new server, you get the error:
Address already in use - bind(2) for "127.0.0.1" port 3000 (Errno::EADDRINUSE)
You can terminate such a dev server with this command:
lsof -t -i :3000 -s TCP:LISTEN | xargs kill -9
It might be worth it to add this to your bash aliases.
Let's assume that we have a model Movie
that registers a callback function when a new instance of Movie
is created (Note: For the purpose of this card it is not important what that callback does or which type of callback it is).
This is how we test whether the callback function (here it is named :my_method
) is called when a new movie is created:
expect_any_instance_of(Movie).to receive(:my_method)
create(:movie) # <-- this is where the method :my_method should be called
You might expect that when calling `create(:mo...
I recently enjoyed debugging a Cucumber step that tried to be retryable using a patiently
block:
Then /^"([^"]*)" should( not)? be selected for "([^"]*)"$/ do |value, negate, field|
patiently do
field = find(:label, text: field)['for'].delete_suffix('-ts-control')
...
end
end
Unfortunately this block is not retryable:
field
.field
, instead of the o...When an object is created / updated, various callbacks are executed in this order:
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit / after_rollback
Thus, each of these callbacks is executed at a specific time in the life cycle of the object. This is important because this point in time determ...
TLDR
if you define a equality method for a class you must also implement
def hash
.
Ruby has a lot of methods that have to do something with equality, like ==
, ===
, eql?
, equal?
. This card should help you differentiate between those and give you hints on how to implement your own equality methods in a safe manner.
==
When you compare two objects in ruby, you most often see the use of foo == bar
. By default the ==
operator inherits from Object
and is impl...
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...
Usually, Unpoly compiler destructors are return
ed from the compiler function.
However, when using async
compiler functions, you can not register destructors via return
.
This will not work:
up.compiler('my-example', async (element) => {
await something
return function onDestroy() {
// ...
}
})
Instead, use up.destructor:
up.compiler('my-example', async (element) => {
await something
u...
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...
tl;dr
You should decouple migrations from models by embedding models into the migration. To use STI in this scenario you have to overwrite
find_sti_class
andsti_name
.
Tip
When possible, try to avoid STI in migrations by disabling it.
Warning
This is more for the sake of I want to do it but I kno...
As a developer you may have many tools watching your project for changes: Your IDE, Webpack, Guard, etc. This is often done with an inotify watcher. If you have too many inotify instances you may run into limits of your operating system.
To find out which process is using them all up you can run:
sudo find /proc/*/fd/ -type l -lname "anon_inode:inotify" -printf "%hinfo/%f\n" | xargs grep -cE "^inotify" | column -t -s:
You will get a list like:
/proc/3753/fdinfo/7 1
/proc/3774/fdinfo/7 1
/proc/4034/fdinfo/12 14
/pr...
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
In Chrome DevTools in the Layouts tab you have handy options to debug CSS Flexbox and Grid. Including:
- Display size and lines along with labels
- Changing their attributes
- Change how overlay is colored and fastly switch nested elements in the Elements panel
This guide will only cover some example gif recordings on how to use with Grid, since it's basically straight forward to apply this for Flexbox by yourself afterwards.
For this purpose a the link to documentation and a simple code pen have been added...
While in CSS zero is usually referenced without specifying a unit (e.g. padding: 0
), you must not use a unitless zero in calc
functions.
You would probably not write something like calc(1rem + 0)
yourself, but it might be the result of a CSS preprocessor (like Sass) or when using custom properties.
The following is invalid:
.example {
--extra-padding: 0;
padding: calc(1rem + var(--extra-padding));
}
That is simply because it is unsupported, as per docum...