The linked article provides a good overview of the various concurrency primitives in Ruby, and what's changing in Ruby 3.
Localizing a non-trivial application can be a huge undertaking. This card will give you an overview over the many components that are affected.
When you are asked to give an estimate for the effort involved, go through the list below and check which points are covered by your requirements. Work with a developer who has done a full-app localization before and assign an hour estimate to each of these points.
app
must be translated: Screens, mailer templates, PDF templates, helpe...PostgreSQL, unlike MySQL, treats strings as case sensitive in all circumstances.
This includes
=
and LIKE
Usually this is fine, but some strings (like emails and usernames) should typically be treated as case insensitive.
There are a few workarounds available:
ILIKE
instead of LIKE
lower()
functionlower(email)
Probably th...
Why improve your code reviews?
Improving code review technique helps your reviewer, your team, and, most importantly: you.
Learn faster: If you prepare your changelist properly, it directs your reviewer’s attention to areas that support your growth rather than boring style violations. When you demonstrate an appreciation for constructive criticism, your reviewer provides better feedback .
Make others better: Your code review techniques set an example for your colleagues. Effective author practices rub off on your teammates, which...
If you want to prevent that two processes run some code at the same time you can use the gem with_advisory_lock.
What happens
- The thread will wait indefinitely until the lock is acquired.
- While inside the block, you will exclusively own the advisory lock.
- The lock will be released after your block ends, even if an exception is raised in the block.
This is usually required if there is no suitable database row to lock on.
You want to generate a...
Within Capybara you most certainly use the #check
- and #uncheck
-method to (un)check checkboxes.
But there's one problem, if you want to test a custom styled checkbox, which hides its <input>
-Tag:
<input>
.Unable to find visible checkbox "Some label" that is not disabled
Use the keyword argument allow_label_click: true
within the method call.
So instead of check('Some label')
, use `check('Some label', allow...
The rubocop
binary has a few interesting flags:
rubocop
(using the --parallel
default ) scans the current repository for linting issues while using multiple CPU coresrubocop -a
(or --autocorrect
) safely corrects most offenses while doing a sequential scan
rubocop -A
(or --autocorrect-all
) also tries to correct unsafe suggestionsAutocorrection takes significantly longer on large projects because of the sequential nature.
To speed things up, you can use the following alias. It first checks in parallel if any files...
Looking at the source code of the validates_numericality_of validator, it becomes clear that it converts the attribute in question to either an integer or float:
if configuration[:only_integer]
unless raw_value.to_s =~ /\A[+-]?\d+\Z/
record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number])
next
end
raw_value = raw_value.to_i
else
begin
raw_value = Kernel.Float(raw_val...
edge_rider is Power tools for ActiveRecord relations (scopes). Please note that some of the functions edge_rider provides have native implementations in newer rails versions.
Edge Rider gives your relations a method #traverse_association
which returns a new relation by "pivoting" around a named association. You can traverse multiple associations in a single call. E.g. to turn a relation of posts into a relation of all posts o...
We often have a separate production branch that lags a bit behind the more cutting edge main branch. Sometimes you want to move some, but not all commits from main to production. This can be done with a git cherry-pick
.
However, this may lead to considerable pain later, since git does not understand the commits are actually "the same". Hazards are unnecessary and hard to resolve conflicts as well as incorrect auto-merges.
In order to avoid this, always merge the production branch back to the main after the cherry-pick. Even t...
Be careful when using buttons without a type
attribute, since browsers will consider them the default submit button of a form.
Suppose you have this form:
<form action="/save">
<input type="text" />
<button onclick="alert('Alert!')">Alert</button>
<button type="submit">Save</button>
</form>
If you press the enter key inside in the text input, browsers will trigger the first button and show the alert.
To fix this, add a type="button"
attribute to the first button.
Rack::SteadyETag
was a Rack middleware that generates the same default ETag
for responses that only differ in XOR-masked CSRF tokens or CSP nonces.
We have deprecated Rack::SteadyETag. We instead recommend reconfiguring your Rails app so two requests to the same resource produce the same HTML for a given user.
Every Rails response has a default ETag
header. In theory this would enable caching for multiple requests to the same resource. Unfortunately the default ETags produced by Rails are effectively random, meaning they can never match a future request.
When your Rails app responds with ETag
headers, future requests to the same URL can be answered with an empty response if the underlying content ha...
CoffeeScript and JavaScript (ECMAScript) both have operators in
and of
. Each language use them for more than one purpose. There is not a single case where the same operator can be used for the same purpose in both languages.
var hasFoo = 'foo' of object
var hasFoo = 'foo' in object;
Iterate through all properties of an object
================================...
Here are some popular mistakes when using nested forms:
fields_for
instead of form.fields_for
.accepts_nested_attributes
in the containing model. Rails won't complain, but nothing will work. In particular, nested_form.object
will be nil
.:reject_if
option lambda in your accepts_nested_attributes
call is defined incorrectly. Raise the attributes hash given to your :reject_if
lambda to see if it looks like you expect.Test Driven Development is the paradigm to "first write a test, then implement the code". This guide shows how to apply it in practice, with Cucumber and RSpec as integration and unit test frameworks.
I like to view TDD as a process with three levels:
During development you are frequently changing levels. It may look something like this:
Integration _ ___
Code \____ _____ __/ \__ ...
Spec ...
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 ...
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
.
source /home/$user/.rbenvrc
in ~/.profile
eval "$(rbenv init -)" in
~/.bashrcor
~/.zshrc`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...
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.
If not configured otherwise, cronjobs defined in whenever's `s...
Building plain text emails with an .erb template doesn't allow you to indent code like you normally do in HTML mails.
<%= '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"
Write unindented code to get the expected result.
<% if bar %>
<%= 'bar' %>
<% end %>
<%= 'foo' %>
<%= 'bar' %>
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...
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...
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}
}
}
}
})
})
expect(actualValue).toBeAnything(...matcherArg...