A Migration Path to Bundler 2+
Bundler 2 introduced various incompatibilites und confusing behavior. To add to the confusion, Bundler's behavior changed after the release of their version 2.
The linked article explains what happened.
Resources for working with the Youtube API
You can use the Youtube API to get data from youtube. Here are some resources and some things that are good to know.
You need to create an API key and each request will cost a certain amount of Request-Points (depending on the kind of query).
It may help to understand youtube's domain model before starting.
It's best to just try out your requests in the browser to see what you will get.
A request can look like this (note that you have to replace the playlis...
Capybara: Execute asynchronous JavaScript
Capybara provides execute_script
and evaluate_script
to execute JavaScript code in a Selenium-controlled browser. This however is not a good solution for asynchronous JavaScript.
Enter evaluate_async_script
, which allows you to execute some asynchronous code and wait until it finishes. There is a timeout of a couple of seconds, so it will not wait forever.
Use it like this:
page.evaluate_async_script(<<~JS)
let [done] = arguments
doSomethingAsynchronous().then(() => {
done() // call this to indicate we're done
})
J...
Email validation regex
There is a practical short list for valid/invalid example email addresses - Thanks to Florian L.! The definition for valid emails (RFC 5322) can be unhandy for some reasons, though.
Since Ruby 2.3, Ruby's URI lib provides a built-in email regex URI::MailTo::EMAIL_REGEXP
. That's the best solution to work with.
/\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[...
WProofreader: How to manually enable for a WYSIWYG editor instance (with CKeditor 4 example)
WProofreader is a spelling and grammar checking tool that integrates with textareas and numerous WYSIWYG editors.
While it usually activates automatically, depending on your application, it may fail to boot.
In my case, an application was using CKEditor 4 and programmatically activated CKEditor. WProofreader's autoSearch
logic failed to hook into that for some reason.
You can choose not to use its autoSearch
feature, but explicitly enable WProofreader.
Here is a guide for CKEditor 4. It should apply to other WYSIWYG editors as well.
1...
Checking database size by row count
As an application exists, data accumulates. While you'll be loosely monitoring the main models' record count, some supportive database tables may grow unnoticed.
To get a quick overview of database table sizes, you can view the row count like this:
PostgreSQL
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC
LIMIT 12;
schemaname | relname | n_live_tup
------------+------------------------------------------------+------------
public | images...
How to enable Chromedriver logging
When using Chrome for Selenium tests, the chromedriver
binary will be used to control Chrome. To debug problems that stem from Selenium's Chrome and/or Chromedriver, you might want to enable logging for the chromedriver itself. Here is how.
Option 1: Use Selenium::WebDriver::Service
In your test setup, you may already have something like Capybara::Selenium::Driver.new(@app, browser: :chrome, options: ...)
, especially when passing options like device emulation.
Similar to options
, simply add an extra key service
and pass an inst...
Bash script to list commits by Pivotal Tracker ID
The main benefit of our convention to prefix commits by their corresponding Pivotal Tracker ID is that we can easily detect commits that belong to the same story. You can either do that manually or use the bash script below by copying it somewhere to your .bashrc
.
# Usage: ptcommits 123456
function ptcommits {
if test "$1"
then
local PTID=$(echo "$1" | grep "[0-9]*" -o) # Allow URLs
git log --onel...
Joining PDFs with Linux command line
There are several ways to merge two (or more) PDF files to a single file using the Linux command line.
If you're looking for graphical tools to edit or annotate a PDF, we have a separate card for that.
PDFtk (recommended)
PDFtk is a great toolkit for manipulating PDF documents. You may need to install it first (sudo apt install pdftk
).
Merging multiple files works like this:
pdftk one.pdf two.pdf cat output out.pdf
Unlike pdfjam, PDFtk should not mess with page sizes but simply joins pages as they are.
...
Known MariaDB version incompatibilities
MariaDB (and MySQL) is released in different versions with different behaviors. For backwards compatibility this can be managed with the sql_mode
option.
Following you can find behavior differences which cannot be changed by this option. This can cause a regression in an existing application. There is no workaround available. The application needs to be adapted.
Queries with aggregated date types
For a database instance of MariaDB-10...
Ruby: How to use global variables for a conditional debugger
You can share a state in Ruby with global variables. Even if you should avoid them whenever possible, for debugging an application this could be temporary quite handy.
Example:
class User
after_save { byebug if $debug; nil }
def lock
self.locked = true
save
end
end
Rspec.describe User do
let(:user) { create(:user) }
before do
# Many users are created and saved in this hook, but we don't want the debugger to stop for them...
Regular Expressions: Excessive backtracking can get yourself in trouble
Two weeks ago, Cloudflare was struck by a global outage that lasted ~30 minutes. The incident was rooted on a CPU exhaustion caused by a single regular expression containing some catastrophic backtracking:
.*(?:.*=.*)
This is a small reminder do keep using the lazy operator ?
whenever possible and furthermore be aware that regular expressions should not only be unit-tested but also evaluated in terms of performance. See <https://makandracards.com/makandra/494822-regul...
Webpack(er): A primer
webpack is a very powerful asset bundler written in node.js to bundle (ES6) JavaScript modules, stylesheets, images, and other assets for consumption in browsers.
Webpacker is a wrapper around webpack that handles integration with Rails.
This is a short introduction.
Installation
If you haven't already, you need to install node.js and Yarn.
Then, put
gem 'webpacker', '~> 4.x' # check if 4.x is still cu...
RubyMine: Efficiently filtering results in the "Finder" overlay
RubyMine comes with a nice way to grep through your project's files: The finder (ctrl + shift + f
). Don't be discouraged about the notice 100+ matches in n+ files
if your searched keyword is too general or widely used in your project.
RubyMine comes with a few ways to narrow down the resulting list, don't hesitate to apply those filters to speed up your search. Your keybinding might vary based on your personal settings.
File mask (alt + k
)
If you already know the file extension of your ...
Jasmine: using async/await to write nice asynchronous specs
Jasmine has long standing support for writing asynchronous specs. In days gone by we used the done
callback to achieve this, but these days it is possible to write much more readable specs.
Async specs
As a first example, say we want to check that some form disables the submit button while working.
// bad (how we used to do it)
beforeEach(() => {
this.form = setupMyForm()
this.submitButton = findTheSubmitButton()
})
it('disables the submit button while working', (done) => {
expect(this.submitButton.disabled).toBe(false)
...
ActiveType 1.2 supports "change_association"
With ActiveType 1.2 you can modify associations (has_many
etc.) after they have been defined.
One common use case for this is to change an association inside a form model, like this:
class Credential < ActiveRecord::Base
end
class User < ActiveRecord::Base
has_many :credentials
end
class SignUpCredential < ActiveType::Record[Credential]
end
class SignUp < ActiveType::Record[User]
change_association :credentials, class_name: 'SignUpCredential'
end
Now, if you load `credentials...
Katapult EOL
Katapult was an endeavor to dramatically speed up starting a new Rails application. However, it turned out to save less time than expected, while requiring more time for maintenance than anticipated. Since its benefits fell too low, we have decided to not continue developing Katapult.
You can still use Katapult for generating ready-to-run applications with model CRUD, authentication and all of Katapult's features, but the rapid development of the web will quickly render the generated code antiquated. Nevertheless, its architecture may remai...
Deal with certain travis CI failures
Travis changed their default distribution from Ubuntu 14.04 (trusty) to 16.04 (precise). This might break your test setup for new builds.
You can solve this issue by freezing your test distribution in the .travis.yml
to Ubuntu 14.04 until you have the time to solve all the issues you will have in 16.04:
dist: trusty
Error details
Here are few indicators that you ran into this issue:
Connection to the PostgreSQL database does not work anymore
Your travis-ci builds might have started failing on the usual
psql -c...
Documenting your Rails project's Node.js version in .nvmrc
Not all versions of Node.js are compatible with each other. Also npm packages may require a minimum or maximum version of Node.js. We use nvm on our development PCs so we can operate multiple versions of Node.js in parallel.
To make sure that all developers use a compatible version of Node.js, your Rails project should declare the required Node.js in a file called .nvmrc
.
When a .nvmrc
exists, developers can cd
in your project directory and activate...
How to recognize CVE-2019-5418
If you get requests with values for formats
like this:
{:locale=>[:de], :formats=>["../../../../../../../../../../etc/services{{"], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml]}
or fails like this:
Invalid query parameters: invalid %-encoding (../../../../../../../../../etc/passwd%%0000.html)
Someone tries to exploit CVE-2019-5418.
If you use the latest Rails (or latest Rails LTS) you're...
Capybara: Testing file downloads
Download buttons can be difficult to test, especially with Selenium. Depending on browser, user settings and response headers, one of three things can happen:
- The browser shows a "Save as..." dialog. Since it is a modal dialog, we can no longer communicate with the browser through Selenium.
- The browser automatically downloads the file without prompting the user. For the test it looks like nothing has happened.
- The browser shows a binary document in its own window, like a PDF. Capybara/Selenium freaks out because there is no HTML docum...
SameSite cookies
TL;DR Most web applications do not require action on this. SameSite=None
(old browser default) will continue to work, and SameSite=Lax
(new Chrome default, gradually rolled out) is an even better default for cookies. Set SameSite=Strict
only for extra security in special cases (see below). If your application is rendered in an iframe (e.g. a video player or some news stream), you need to configure its relevant cookies as SameSite=None
.
The SameSite
cookie attribute targets **c...
Self-expiring URLs with Apache
When delivering non-public uploaded files (images, documents etc), one has to decide whether and how to do authorization. The usual approaches are:
- Using
send_file
with a regular controller. This is secure, but potentially slow, especially for large collections of images. - Using unguessable URLs. This is fast (because Apache can deliver assets without going through Rails), but less secure.
When going with the "unguessable URL" approach, it is possible to somewhat increase security by using expiring URLs. The idea is to encode the expi...
Function Composition in Ruby
Along with a number of other cool new features and performance improvements, Ruby 2.6 added function composition to the Proc and Method classes. Today we’ll take a look at how this allows us to use some functional programming goodness in our Ruby code.