Popular mistakes when using nested forms
Here are some popular mistakes when using nested forms:
- You are using
fields_for
instead ofform.fields_for
. - You forgot to use
accepts_nested_attributes
in the containing model. Rails won't complain, but nothing will work. In particular,nested_form.object
will benil
. - The
:reject_if
option lambda in youraccepts_nested_attributes
call is defined incorrectly. Raise the attributes hash given to your:reject_if
lambda to see if it looks like you expect. - If you are nesting forms into nested forms, each model involved ne...
Test-Driven Development with integration and unit tests: a pragmatic approach
Test-Driven Development (TDD) in its most dogmatic form (red-green-refactor in micro-iterations) can be tedious. It does not have to be this way! This guide shows a pragmatic approach with integration and unit tests, that works in practice and improves on productivity.
Advantages
- No added effort: tests need to be written anyway.
- Test heads serve as todo lists. You'll always know what is finished and what is left to do.
- Big tasks are broken down into smaller tasks that can be processed one by one.
- You will not forget a test.
- You...
Modern CSS supports individual transform properties
tl;dr
Individual transform properties are great because they allow you to write more readable and maintainable CSS, especially when applying multiple transformations and/or when animating transforms.
For ages, CSS transforms had to be defined using the transform
property. For a single transformation, this was something like transform: scale(1.5)
, and multiple transformations could be applied by chaining them.
.example {
transform: scale(1.5) rotate(45deg) translateY(-50%);
}
All modern browsers (Chrome & Edge ...
ASDF: A Version Manager To Rule Them All
tl;dr
asdf
allows you to manage multiple runtime versions with a single CLI tool and is backwards compatible by supporting existing config files, like e.g..nvmrc
or.ruby-version
.
Getting Started
- Disable rbenv
1.1 Delete or comment outsource /home/$user/.rbenvrc
in~/.profile
1.2 Delete or comment oureval "$(rbenv init -)"
in~/.bashrc
or~/.zshrc
1.3 To take effect you may have to restart your shell or log out and log in again from your current linux session - Install asdf by following the official ...
Jasmine: Preventing unhandled promise rejections from failing your test
You have an async function that rejects:
async function failingFunction() {
throw new Error("Something went wrong")
}
When you call that function in a test, your test will fail:
it('has a test', function() {
failingFunction() // this will fail your test
})
The failure message will look like this:
Unhandled promise rejection: Error: Something went wrong
You can fix this by expecting the state of the returned promise:
it('has a test', async function() {
await expectAsync(failingFunction()).toBeRej...
Decide whether cronjobs should run on one or all servers
Understanding your type of cronjob
Some cronjobs must only run on a single server. E.g. when you run nightly batch operations on the database, it should probably run on a single server. Running it on multiple servers would likely result in deadlocks or corrupt data.
Some cronjobs must always run on all servers. E.g. starting a sidekiq process on reboot.
Configuring whenever
If not configured otherwise, cronjobs defined in whenever's `s...
Take care of indentation and blank lines when using .erb for plain text emails
Building plain text emails with an .erb template doesn't allow you to indent code like you normally do in HTML mails.
❌ DON'T
<%= 'foo' if bar %>
"\n"
if bar is false
"foo\n"
if bar is true
<%= nil %>
"\n"
<% if true %>
<%= 'foo' %>
<% end %>
" foo"
<%= 'foo' %>
<%= 'bar' %>
"foo\n\nbar\n"
✔️ DO
Write unindented code to get the expected result.
<% if bar %>
<%= 'bar' %>
<% end %>
<%= 'foo' %>
<%= 'bar' %>
- Use [Form Models](https://github.com/makandr...
RSpec: Run a single spec (Example or ExampleGroup)
RSpec allows you to mark a single Example/ExampleGroup so that only this will be run. This is very useful when using a test runner like guard.
Add the following config to spec/spec_helper.rb
:
RSpec.configure do |config|
# These two settings work together to allow you to limit a spec run
# to individual examples or groups you care about by tagging them with
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
# get run.
config.filter_run_including :focus => true
config.run_all_when_everything_filtere...
CSP: strict-dynamic
tl;dr
The
strict-dynamic
source list keyword allows you to simplify your CSP policy by favoring hashes and nonces over domain host lists.The key super power of
strict-dynamic
is that it will allow to load additional scripts via non-"parser-inserted" script elements.
For unsupported browsers, your script can be made backwards compatible by doing something like this:
script-src 'nonce-rAnd0m' 'strict-dynamic' https: 'self'
default-s...
Jasmine: Adding custom matchers
Definition
A matcher is a function that returns an object with a compare
key. Usually it is registered with beforeEach
:
beforeEach(() => {
jasmine.addMatchers({
// Example matcher
toBeAnything() {
return {
compare(actualValue, ...matcherArguments) {
// Do some computations here ...
// Return whether the actualValue matches the expectation
return {pass: true}
}
}
}
})
})
Usage
expect(actualValue).toBeAnything(...matcherArg...
Use find_in_batches or find_each to deal with many records efficiently
Occasionally you need to do something directly on the server -- like having all records recalculate something that cannot be done in a migration because it takes a long time.
Let's say you do something like this:
Project.all.each(&:recalculate_statistics!)
Even though you may have been successful with this on your development machine or the staging server, keep in mind that production machines often hold a lot more records. Using all
may just work, even with lots of records, but when you iterate over such records and fetch a...
CSS: Combining different length units with calc()
calc()
lets you mix CSS units. Ever wanted to give an element "the container's width minus 20px on each side"? Here you go:
.foo {
width: calc(100% - (20px * 2));
}
When using Sass, you need to interpolate Sass expressions:
$margin: 20px * 2
.foo
width: calc(100% - #{$margin})
Supported by all modern browsers and IE9+.
How to fix: irb / rails console randomly crashing
If your irb or rails console keeps randomly crashing and you can't figure out why then you can try to disable multi-line autocomplete.
Sidekiq 7: Rate limiting with capsules
Sidekiq 7 adds a new feature called capsules.
Use cases:
- a
chrome
queue limited to1
for e.g. PDF processing to not overload the application server - an
api
queue, that limits a queue to2
to protect the API server from too many requests in parallel
Example:
Sidekiq.configure_server do |config|
# Edits the default capsule
config.queues = %w[critical default low]
config.concurrency = 5
# Define a new capsule which ...
ActiveRecord::Relation#merge overwrites existing conditions on the same column
In Ruby on Rails ActiveRecord::Relation#merge
overwrites existing conditions on the same column. This may cause the relation to select more records than expected:
authorized_users = User.where(id: [1, 2])
filtered_users = User.where(id: [2, 3])
authorized_users.merge(filtered_users).to_sql
# => SELECT * FROM users WHERE id IN (2, 3)
The merged relation select the users (2, 3)
, although we are only allowed to see (1, 2)
. The merged result should be (2)
.
This card explores various workarounds to combine two scopes so t...
Using the Oklch color space to generate an accessible color palette
The linked content describes:
- The different color space of Oklch and RGB/HSL (HDR colors)
- The advantage of Oklch when you change a base color and your derived colors will keep the same assertions on contrast level
Warning
This feature landed in browsers at the end of 2022. According to our support policy this will become generally usable starting Dec 2024.
The oklch() functional notation expresses a given color in the Oklch color space. It has the same L axis as oklab(), but uses polar coordinates C (Chroma) and H (Hue).
Sour...
Understanding database Indexes in PostgreSQL
I found the linked article very helpful to refresh my understanding of database indexes. As a small bonus, it includes a few helpful SQL oneliners like these two:
Warning
Do not run random code snippets unless you understand them in detail - especially in production.
How to create a multiline map in SASS/SCSS
If you want to to create maps within SASS/SCSS-files, it normally works like this:
$some-map: (key1: value1, key2: value2)
However, some maps can get big really fast, if they are being used to contain all of the project's icon names and their sizes for example.
Therefore splitting a map into multiple lines, like we do it in Ruby with big hashes, would become really handy.
Unfortunately SASS doesn't support multiline maps. There has been an open issue since 2011 and it hasn't been...
Rubymine: Configure CTRL + ALT + SHIFT + c to work with "Test Source Roots"
To navigate between test and test subject Rubymine requires you to set the test root sources as Test Sources Root.
In case you are using the keyboard shortcut "CTRL + ALT + SHIFT + c" to copy the reference path + you have set the "Test Sources Root" for your test folders, you might consider setting this keyboard to "Copy From Repository Root". This will return the path `spec/foo_spec....
Webpacker: Configuring browser compatibility
Webpacker uses Babel and Webpack to transpile modern JavaScript down to EcmaScript 5. Depending on what browser a project needs to support, the final Webpack output needs to be different. E.g. when we need to support IE11 we can rely on fewer JavaScript features. Hence our output will be more verbose than when we only need support modern browsers.
Rails 5.1+ projects often use Webpacker to preconfigure the Webpack pipeline for us. The default configuration works something like this:
- Webpack checks w...
Do not use transparent PNGs for iOS favicons
Safari on iOS accepts an apple-touch-icon
favicon that is used for stuff like desktop bookmarks. Always define a solid background color for them.
If you use PNGs with a transparent background, Safari will use just set a black background on your pretty icon. This is almost never what you want.
You can fix that by applying a white background via ImageMagick like this:
convert a...
Verifying doubles in RSpec 3
RSpec 3 has verifying doubles. This breed of mock objects check that any methods being stubbed are present on an instance of a given class. They also check methods aren't called with the wrong number of arguments.
This dual approach allows you to move very quickly and test components in isolation, while
giving you confidence that your doubles are not a complete fiction.
You should always prefer using a verifying double to using an old-school mock
...
How Haml 6 changes attribute rendering, and what to do about it
Haml 6 was a major rewrite with performance in mind. To achieve a performance improvement of 1.7x, some design trade-offs had to be made. The most notable change might be the simplified attribute rendering.
In Haml 5, attribute rendering knew two special cases: an attribute with value true
would be rendered without a value, an attribute with a falsy value would not be rendered at all. All other values would just be rendered as attribute values.
According to the Haml maintai...
Rails: Assigning associations via HTML forms
Let's say we have posts with an attribute title
that is mandatory.
Our example feature request is to tag these posts with a limited number of tags. The following chapters explain different approaches in Rails, how you can assign such an association via HTML forms. In most cases you want to use Option 4 with assignable values.
The basic setup for all options looks like this:
config/routes.rb
Rails.application.routes.draw do
root "posts#index"
resources :posts, except: [:show, :destroy]
end
**db/migrate/...