Using attribute event handlers with a strict Content Security Policy (CSP)
Given you have a strict CSP that only allows <script src>
elements from your own domain:
Content-Security-Policy: script-src 'self'
This will block JavaScript handlers inlined as attribute into your HTML elements. Clicking on the following link will only log an error with a strict CSP:
<a href="javascript:alert('hello')">click me</a>
<a href="#" onclick="alert('hello')">click me</a>
Solution 1: Move the handler into your JavaScript
The recommended solution is to move the handler from the HTML to the allowed ...
RSpec: Debug flickering test suites with rspec --bisect
In modern default RSpec configurations, your tests are usually run in random order. This helps to detect "flickering" tests that only fail when run in a certain order.
The reason for this are tests that have side effects causing other tests to fail later. The hard part is to find the offending test.
Enter rspec --bisect
:
- Say you have a flickering test that passes on its own, but you just saw it fail in a full test run. At the top of the RSpec output, you will see a message like
Randomized with seed 12345
. Take a note of the number....
CSS has a well-supported :empty selector
All browsers + IE9 know the CSS :empty
selector. It lets you hide an element when it has no content, i.e. not even white space.
(How to prevent whitespace in HAML)
For instance, you have a badge displaying the number of unread messages in a red bubble with white text:
.unread-messages-bubble {
background-color: red;
border-radius: 10px;
padding: 10px;
color: white;
}
To hide that bubble entirely ...
SSL/TLS - Typical problems and how to debug them
The linked article provides a description of commonly found problems with TLS and hints on debugging / solving them.
Don't forget: Automatically remove join records on has_many :through associations
Bad
# Given the following models
class Image < ActiveRecord::Base
has_many :album_images
has_many :albums, through: :album_images
end
class Album < ActiveRecord::Base
has_many :album_images
has_many :images, through: :album_images
end
# Join model
class AlbumImage < ActiveRecord::Base
belongs_to :album
belongs_to :image
end
Destroying a record in this setup will only remove the record itself, and leave orphaned join records behind.
image = Image.last
image.destroy # removes only the `image` record,
...
RSpec < 2.11: ActiveRecord scopes must be loaded before using the "=~" matcher
To test whether two arrays have the same elements regardless of order, you can use the =~
matcher in RSpec < 2.11:
actual_array.should =~ expected_array
If either side is an ActiveRecord scope rather than an array, you should call to_a
on it first, since =~
does not play nice with scopes:
actual_scope.to_a.should =~ expected_scope.to_a
If you use RSpec >= 2.11 we recommend using the match_array
or contain_exactly
matchers instead of =~
.
Use the eq
matcher only if the order of records matters.
Default Arguments and Memoized
tl;dr: Avoid to memoize methods with default (keyword) arguments!
When you are using Memoized with default arguments or default keyword arguments, there are some edge cased you have to
keep in mind.
When you memoize a method with (keyword) arguments that have an expression as default value, you should be aware
that the expression is evaluated only once.
memoize def print_time(time = Time.now)
time
end
print_time
=> 2021-07-23 14:23:18 +0200
sleep(1.minute)
print_time
=> 2021-07-23 14:23:18 +0200
When you memoize a met...
Using multiple MySQL versions on the same linux machine using docker
We had a card that described how to install multiple mysql versions using mysql-sandbox
. Nowadays with the wide adoption of docker it might be easier to use a MySQL docker image for this purpose.
Create a new mysql instance
docker run --name projectname_db -e MYSQL_ROOT_PASSWORD=secret -p "33008:3306" -d --restart unless-stopped mysql:5.7
The port 33008 is a freely chosen free port on the host machine that will be used to establish a con...
How to extract a Ruby gem
The rubygems binary gem
allows to extract a local gem with gem unpack GEMNAME
. For more details see the official documentation.
This was useful for compliance checks, when it was necessary to check the license of the C-files in nokogiri
.
CarrierWave: When your uploader generates filenames dynamically, use model.save! instead of uploader.recreate_versions!
If your Carrierwave uploader dynamically generates the filename (e.g. by incorporating a user's name), you must call model.save!
after recreating versions.
uploader.recreate_versions!
does not update the model with the stored filename.
Debugging AJAX requests with better_errors
better_errors
is an awesome gem for enhanced error pages in development, featuring a live-REPL for some light debugging.
To debug the exception you got on an AJAX-Request, visit /__better_errors
on your app's root path (e.g. http://localhost:3000/__better_errors
). It shows the error page for the last exception that occurred, even when it has been triggered by an AJAX request.
CSS: How to force background images to scale to the container, ignoring aspect ratio
You can scale background images in CSS to the container size using background-size
(Demo).
Commonly, we use contain
or cover
because we want to preserve the image's aspect ratio.
If you do not want to do that, simply provide scaling values for X and Y:
background-size: 100% 100%
(a simple 100%
would mean 100% auto
and respect the image's aspect ratio)
SVGs with a viewBox will force their aspect ratio
The above may not work for you when ...
Ruby: What extend and include do
All Rubyists should be familiar with the common definitions for include and extend. You include a module to add instance methods to a class and extend to add class methods. Unfortunately, this common definition isn’t entirely accurate. It fails to explain why we use instance.extend(Module) to add methods to an instance. Shouldn’t it be instance.include(Module)? To figure this out we’re going to start by discussing where methods are stored.
- include: Adds methods from the provided Module to the object
- extend: Calls include on the single...
Setting SASS variables as value for CSS custom properties
When using custom properties in your stylesheets, you may want to set a specific property value to an existing variable in your SASS environment. A pratical example would be a list of color variables that you've defined in colors.sass
and that you would like to refer to in your stylesheets. However, simply assigning a variable will not work:
$my-great-blue: blue
:root
--my-color: $my-great-blue
.sky
background-color: var(--my-color)
The property value will not be valid and if you open the browser's inspection window, yo...
Headless Chrome: Changing the Accept-Language header is not possible
It seems like changing the HTTP_ACCEPT_LANGUAGE
is not possible for a headless chrome.
- On Ubuntu the headless Chrome derives the Accept-Language from the operation system
- Adding the option
options.add_argument('--lang=de')
to theCapybara::Selenium::Driver
has no effect - Adding the preference
options.add_preference('intl.accept_languages', 'de')
to theCapybara::Selenium::Driver
has only effects if the--headless
option is skipped (see bug ticket #775911) - Cha...
Selenium: Network throttling via Chromedriver
You can throttle the network in your headless chrome via Selenium. This might be useful for debugging issues with flaky integration tests or slow page simulations.
page.driver.browser.network_conditions = {offline: false, latency: 5, download_throughput: 2 * 1024, upload_throughput: 2 * 1024}
The settings will match to the following UI component in Chrome:
Were the values for the default profiles might match the values from this post:
**S...
List of Chromium Command Line Switches « Peter Beverloo
An extensive list of command line options when booting Chrome.
This is useful for building a Capybara driver with custom Chrome options.
Gatekeeping: Guide for developer
If your project manager wants to do gatekeeping on a project, as a developer you need to follow the following guidelines (e.g. by using something like this issue checklist template).
In order to reduce the number of rejects we get from clients, we want to review all code written before it goes to the staging server.
Note: This process is tailored to our specific needs and tools at makandra. While it will certainly not apply to all (especially larger tea...
Yarn: if integrity check won't let you start rails console
I ran into a situation in which I received the yarn integrity check warning when starting the rails console even though everything was up to date and correct versions in use.
TLDR: run spring stop
I tried starting the rails console without switching to the correct node version first and received the yarn integrity warning.
warning Integrity check: System parameters don't match
error Integrity check failed ...
Ruby: required keyword arguments in the pre-2.1 era
Starting with Ruby 2.0 you can define methods with keyword arguments.
In 2.1+ required keyword arguments can be defined by using a colon without default value:
def match(value, ignore:)
# ...
end
To accomplish something similar in ruby 1.8, use:
def match(value, options = {})
ignore = options.fetch(:ignore)
# ...
end
How to avoid raising RestClient exceptions for 4xx or 5xx results
When using RestClient to make an HTTP request, it will raise an exception when receiving a non-successful response.
HTTP status codes like 422 or 403 might be totally expected when talking to APIs, so plastering your code with rescue RestClient::Exception
or similar can feel annoying.
It may not be intuitive, but the readme says you can also pass a block to methods like RestClient.get
or RestClient::Request.execute
. In that case, RestClient will not raise ...
Die Grenzen von SEO: was Suchmaschinenoptimierung nicht ist
Der verlinkte Artikel grenzt präzise ab, welche Aufgaben zur Suchmaschinenoptimierung (SEO) gehören und welche nicht.
Suchmaschinenoptimierung ist eine Querschnittsfunktion: die Arbeit vieler unterschiedlicher Abteilungen hat Einfluss auf den SEO-Erfolg der Firma. In diesem Beitrag versuchen wir deswegen, den Kern von SEO zu definieren.
Don't use migrations to seed default data
Don't insert table rows in a Rails database migration. This will break tests that expect that database to be empty and cause you all sorts of pain.
If you need a place for default application data, use db/seed.rb or put a script into lib/scripts
. It won't run automatically, so add a chore story to Pivotal Tracker as a reminder.
GitHub Actions: Manually running a workflow
To start a workflow manually it must have a trigger called workflow_dispatch
:
---
name: Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
branches:
- master
In the Actions tab of your repo you can now select a workflow and press "Run Workflow".