Added a general advise to migration models: Using reset_column_information
should prevent some common issues when migrating from scratch.
While it might seem trivial to implement an invoice that sums up items and shows net, gross and vat totals, it actually involves a lot of rules and caveats. It is very easy to create invoices where numbers don't add up and a few cents are missing. A missing cent is a big deal for an accountant, so it is important for your invoices to list correct numbers.
Note that this is not legal advice. Also note that while this note has a number of code examples in Ruby and MySQL, the concepts apply to all programming languages and data stores.
When ...
Sometimes you want to find the inverse of an ActiveRecord scope. Depending on what you want to achieve, this is quite easy with Rails 7, and a bit more complicated with Rails 6 and below, or when the inverse scope may contain NULL values. [1]
As an example, consider the following model.
class User < ApplicationRecord
scope :admins, -> { where(role: ['admin', 'superuser']) }
# ...
end
Now what if we want a scope of users that are not admins? While you could declare a second scope like `scope :non_admins, -> { where(role: ['...
We tend to use database transactions as a magic bullet to get rid of all our concurrency problems. When things get really bad, we might even throw in some locking mechanism, but then are usually done with it.
Unfortunately, transactions semantics in databases are actually very complicated, and chances are, your making some incorrect assumptions.
The MySQL innodb engine actually has [four different modes](ht...
tl;dr When browsers start to adapt proposals from Open UI, it might not be necessary to use any 3rd party libraries to have nice components and controls in web applications e.g. selects. It would require only a minimum of CSS and Javascript to get them working and looking good.
The purpose of the Open UI, a W3C Community Group, is to allow web developers to style and extend built-in web UI components and controls, such as dropdowns, checkboxes, radio buttons, and date/color pickers.
To do that, we’ll need to fully specify ...
This card describes different flavors for concatting HTML safe strings in a helper method in Rails. You might want to use the tag helper instead of the content_tag helper (the tag
helper knows all self closing tags).
We want to generate HTML like this:
<h1>Navigation</h1>
<ul>
<li>Left</li>
<li>Right</li>
</ul>
Below you ca...
Tests are about 100% control over UI interaction and your test scenario. Randomness makes writing tests hard. You will also push tests that are green for you today, but red for a colleague tomorrow.
That said, please don't do something like this:
Factory(:document) do |document|
document.category { ['foo', 'bar', 'baz'].sample }
end
Instead do this:
Factory(:document) do |document|
document.category 'foo'
end
I even recommend to not use libraries like [Faker]...
One of the earliest pieces of wisdom we are given as programmers is to not write duplicate code: Don’t Repeat Yourself (or DRY if you prefer). Identical blocks of code to set up a test sure does look like repetition, so we extract it into a before block.
This is a mistake for tests.
The article explains about how sharing setup between examples make test files harder to read and evolve.
A related frustration I have is working on ultra-DRY & betterspecs-like ...
The following two hints are taken from Github's Ruby style guide:
If your regular expression mentions a lot of forward slashes, you can use the alternative delimiters %r(...)
, %r[...]
or %r{...}
instead of /.../
.
%r(/blog/2011/(.*))
%r{/blog/2011/(.*)}
%r[/blog/2011/(.*)]
If your regular expression is growing complex, you can use the /x
modifier to ignore whitespace and comments:
regexp = %r{
start # some text
\s # white space char
(group) ...
Postgres works differently
See PostgreSQL: Difference between text and varchar columns for PostgreSQL-specific info
MySQL has 4 different column sizes. They are actually different data types under the hood:
type | size limit | schema.rb option |
---|---|---|
TINYTEXT | 256 bytes | size: :tiny |
TEXT | 65,535 bytes | (default) |
MEDIUMTEXT | 16,777,215 bytes | size: :medium |
LONGTEXT | 4,294,967,... |
TLDR: In tests you need to clean out the database before each example. Use :transaction
where possible. Use :deletion
for Selenium features or when you have a lot of MyISAM tables.
You want to clean out your test database after each test, so the next test can start from a blank database. To do so you have three options:
DatabaseCleaner.strategy = :transaction
or `config.use_transactional_fi...Regular expressions in Javascript are represented by a RegExp
object. There also is a regex literal as in many other languages: /regex/
. However, they are used slightly differently.
/foo+/
RegExp("foo+")
or new RegExp("foo+")
RegExp("\\d+")
HTML <video>
elements can automatically start playing when the autoplay
attribute is set on them. Except for when they can not, e.g. on pageload, or when the element enters the DOM without user interaction, or when the browser for some other reason decided to not start playing the video.
While there is no native "autoplay failed" event to listen to, you can wait for video data to be loaded and then check if the video actually started playing.
<video autoplay>
<source src="example.mp4" type="video/mp4" />
</video>
...
Debugging performance issues in your Rails app can be a tough challenge.
To get more detailed insights consider using the rack-mini-profiler gem.
Add the following gems:
group :development do
gem 'memory_profiler'
gem 'rack-mini-profiler'
gem 'stackprof'
end
Unpoly will interfere with the rack-mini-profiler widget, but configuring the following works okayish:
// rack-mini-profiler + unpoly
if (process...
There are two ways a logout in SAML can happen: Service Provider (SP) initiated and Identity Provider (IDP) initiated logout. I'll explain how to implement both flows with devise_saml_authenticatable
.
Note
SAML also supports a
SOAP
and anArtifact
binding to do this. This guide only refers toPOST
andRedirect
bindings.devise_saml_authenticatable
does not supportSOAP
andArtifact
bindings.
When the user clicks on Logout
within the app, the app can trigger...
Starting with Rails 7.1 the production logger is set to standard out. For applications running with opscomplete ensure to keep logging to a file as before (e.g. when running bin/rails app:update
).
It should be enough to change these lines in the config/environments/production.rb
back to the implementation in Rails <7.1:
- # Log to STDOUT by default
- config.logger = ActiveSupport::Logger.new(STDOUT)
- .tap { |lo...
Note
Using rem only ever makes sense when the root font size is dynamic, i.e. you leave control to the user. Either by a) respecting their user agent defaults, or by b) offering multiple root font sizes in your application.
By defining @media queries in rem, they will accommodate to the root font size of your page. At a larger root font, breakpoints will be at larger widths, scaling with the font. However, there is a catch in case b) mentioned in the note above.
Relative length units in media queries are based on the initial value,...
If you are using git submodules in Gitlab CI, you might run into a "The project you were looking for could not be found or you don't have permission to view it."
Gitlab added a feature that new projects are no longer allowed to be cloned inside CI runs of other repositories by default. To fix this
The standard way to abort async code is that your function takes a AbortSignal
{ signal }
property. The caller can use this signal to send an abort request to your function. Upon receiving the request, your function should reject its promise with an error.
Async browser functions like fetch()
reject their promises with a new DOMException('Message here', 'AbortError')
when canceled.
This already has good browser support and can be polyfilled on older browsers.
Turns out, Cucumber::MultilineArgument::DataTable#diff!
caches some stuff. Code of the following form will not work as intended:
Then('some table should look like') do |expected_table|
patiently do
actual_table = calculate_actual_table
expected_table.diff!(actual_table) # not actually patient, will keep failing if it failed the first time
end
end
Instead, simply use
expected_table.dup.diff!(actual_table)
Developing or debugging SAML functionality can be a hassle, especially when you need to go back and forth with someone external who is managing the identity provider (IDP).
But you can setup a local keycloak server to act as your IDP to play around with. This might seam intimidating, but is actually quite simple when using docker and turning off some verification steps.
`mkdir -p keycloak_data && docker run --network=host -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN...
If you need to make an HTTPS connection to a host which uses an expired certificate, do not disable certificate verifications entirely. Doing that enables e.g. man in the middle attacks.
If you accept only a single expired and known certificate, you are much less in trouble.
All the solutions described below use a verify_callback
for the request's OpenSSL::X509::Store
where you can specify a lambda to adjust its verification response.
Your callback must return either true
or false
and OpenSSL's verification result is...
Due to network or hardware failures, it can happen that one of your cronjobs will not run at the time you specify in the schedule. Your code should be built in a way that it can be re-run at a later time (when the failure is resolved).
For example, if you are synchronizing data with another service once every day, your cronjob should not only synchronize changes from the last 24 hours. If you do this and a network failure will delay the execution of your job by 5 hours, you will only synchronize changes from hour 6-29, but forget change...
This card existed before, but was outdated due to browser implementation changes. The information below is validated for the current list of browsers we support.
By default your html
and body
elements are only as high as the actual page content inside their container. If you only have two lines of text in your page, your html
and body
elements will only be around 40 pixels high, regardless of the size of your browser window.
You might be surprised by this, since setting a background
on either html
and `body...