Event order when clicking on touch devices
Touch devices have their own set of events like touchstart
or touchmove
. Because mobile browsers should also work with with web applications that were build for mouse devices, touch devices also fire classic mouse events like mousedown
or click
.
When a user follows a link on a touch device, the following events will be fired in sequence:
touchstart
touchend
mousemove
mousedown
mouseup
click
Canceling the event sequence
-------------------...
Bash: How to use colors in your tail output
Sometimes it's nice to have some coloring in your logs for better readability. You can output your logs via tail
and pipe this through sed
to add ANSI color annotations (which your console then interprets).
To print a log (e.g. rails log) and color all lines containing "FATAL" in red and all lines with "INFO" in green:
tail -f /path/to/log | sed --unbuffered -e 's/\(.*INFO.*\)/\o033[32m\1\o033[39m/' -e 's/\(.*FATAL.*\)/\o033[31m\1\o033[39m/'
Here are the ...
Capybara: How to find a hidden field by its label
To find an input with the type hidden, you need to specify the type hidden
:
find_field('Some label', type: :hidden)
Otherwise you will see an exception :
find_field('Some label')
# => Capybara::ElementNotFound: Unable to find field "Some label" that is not disabled`.
Note: Usually you don't need to check the input of hidden fields in an integration test. But e.g. waiting for a datepicker library to write the expected value to this field before continuing the test, which prevents flaky tests, is a valid use case.
Quick HTML testing with RubyMine
If you need to test some HTML, e.g. an embed code, you can use RubyMine's "scratch files":
- File > New Scratch File (or
Ctrl + Shift + Alt + Ins
) - Select "HTML" as file type
- Write or paste the HTML
- Move your mouse to the upper right corner of the scratch file editor. Pick a browser to instantly open your file.
Letting a DOM element fade into transparency
You can use the CSS property mask-image
to define an "alpha channel" for an element.
E.g. to let an element start at full opacity at the top and gradually fade into transparency at the bottom:
.box {
-webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
}
- A fully opaque black pixel will render the masked pixel fully opaque
- A fully transparent black pixel will render the ...
Traversing the DOM tree with jQuery
jQuery offers many different methods to move a selection through the DOM tree. These are the most important:
$element.find(selector)
Get the descendants of each element in the current set of matched elements, filtered by a selector. Does not find the current element, even it matches. If you wanted to do that, you need to write $element.find(selector).addBack(selector)
.
$element.closest(selector)
Get the first ancestor el...
Ruby: How to fetch a remote host's TLS certificate
TLS/SSL certificates are often used for HTTPS traffic. Occasionally a service may also use their TLS certificate to support public-key encrypting data (e.g. when it is part of the URI and visible to the user, but contains sensitive information).
Here is how to easily fetch such certificate data.
certificate = Net::HTTP.start('example.com', 443, use_ssl: true) { |http| http.peer_cert }
# => #<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name CN=www.example.org,...>
certificate.public_key
# => #<OpenSSL::PKey::RSA:0x...
Sass partial names must always start with an underscore
Be careful to name any file @import
ed by SASS with a leading underscore.
SASS files not beginning with an underscore will be rendered on their own, which will fail if they are using variables or mixins defined elsewhere. (For me it broke only in production, which may be due to some settings in SASS-GEM/lib/sass/plugin/rails.rb
.)
From the SASS docs:
The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.
Inspecting a live Ruby process
How to get a backtrace from a running Ruby process:
Ruby 2.6
# First, find out the PID of your Ruby process (e.g. passenger-status)
$ sudo gdb -p PID
(gdb) call rb_eval_string("$stderr.reopen('/tmp/ruby-debug.' + Process.pid.to_s); $stderr.sync = true") # redirects stderr
(gdb) call rb_backtrace() # prints current backtrace to /tmp/ruby-debug.xxx
Stop the process afterwards, since stderr is now borked.
It is possible you have to call rb_backtrace()
multiple times to get the full stacktrace.
Previous method on Ruby 2....
How to use the Capistrano 2 shell to execute commands on servers
Capistrano 2 brings the shell
command which allows you to run commands on your deployment targets.
There is also invoke
to run a command directly from your terminal.
Both commands allow running Capistrano tasks or shell commands, and scope to individual machines or machine roles.
Unfortunately Capistrano 3 does not include these commands any more.
cap shell
Basics
First of all, spawn a Capistrano shell (we're using the multistage
extension here):
$ cap staging shell
In your "cap" shell you can now run Capistrano ta...
Guide to String Encoding in Ruby
The linked article has a great explanation how to to deal with string encodings in Ruby. Furthermore you can check out some of our cards about encoding:
How to make a cucumber test work with multiple browser sessions
Imagine you want to write a cucumber test for a user-to-user chat. To do this, you need the test to work with several browser sessions, logged in as separate users, at the same time.
Luckily, Capybara makes this relatively easy:
Scenario:
Scenario: Alice and Bob can chat
Given Alice, Bob, and a chat session
When I am signed in as "Alice"
And I go to the chat
And I am signed in as "Bob" [session: bob]
And I go to the chat [session: bob]
And I send the message "Hello, this is Alice!"
Then I should see "Hello, this ...
Rails: Rest API post-mortem analysis
This is a personal post-mortem analysis of a project that was mainly build to provide a REST API to mobile clients.
For the API backend we used the following components:
- Active Model Serializer (AMS) to serializer our Active Record models to JSON.
- JSON Schema to test the responses of our server.
- SwaggerUI to document the API.
It worked
The concept worked really good. Here are two points that were extraordinary compared to normal Rails project with many UI components:
- Having a Rails application, that has no UI components (only...
How to: Validate dynamic attributes / JSON in ActiveRecord
PostgreSQL and ActiveRecord have a good support for storing dynamic attributes (hashes) in columns of type JSONB
. But sometimes you are missing some kind of validation or lookup possibility (with plain attributes you can use Active Record's built-in validations and have your schema.rb
).
One approach about being more strict with dynamic attributes is to use JSON Schema validations. Here is an example, where a project has the dynamic attributes analytic_stats
, that we can use to store analytics from an external measurement tool.
- A g...
Handling duplicate links with Capybara and Cucumber
Sometimes, you might have duplicate links on a page. Trying to click those links will by default cause Capybara to raise an Ambiguous match
error.
If you do not care about which of those links are clicked, you can disable this errors by adding the following meta step:
When(/^(.*) \[allow ambiguous\]$/)do |step_text|
prior_match_strategy = Capybara.match
Capybara.match = :first
step(step_text)
ensure
Capybara.match = prior_match_strategy
end
Use it with
When I follow "a duplicate link" [allow ambiguous]
Structuring Rails applications: the Modular Monorepo Monolith
Root Insurance runs their application as a monolithic Rails application – but they've modularized it inside its repository. Here is their approach in summary:
Strategy
- Keep all code in a single repository (monorepo)
- Have a Rails Engine for each logical component instead of writing a single big Rails Application
- Build database-independent components as gems
- Thus: gems/ and engines/ directories instead of app/
- Define a dependency graph of components. It should have few edges.
- Gems and Engines can be extracted easier once nece...
Capybara 'fill_in': Ambiguous match for different input names
When you have two inputs, where one contains the name of the other (eg. Name
and Name with special treatment
), Capybara's fill_in
method will fail with the following message:
Ambiguous match, found 2 elements matching visible field "Name" that is not disabled (Capybara::Ambiguous)
You can force Capybara to match exactly what you are typing (which makes your tests better anyways) with match: :prefer_exact
:
name = 'Name'
value = 'Bettertest Cucumberbatch'
fill_in(field, with: value, match: :prefer_exact)
Furthermore...
How to capture a screen-cast on Linux
Recording
SimpleScreenRecorder
I recommend simplescreenrecorder, it produces an adequate output with only a few clicks. The audio recording contained some static noises, but that might be caused by my microphone.
Recording only a single screen or fixed rectangle is supported. The video quality seems quite grained when using the default settings - I found that using the MKV container, H.264 codec, "0" constant rate factor and "veryslow" preset results in the best video quality.
###...
Jasmine: Test that an object is an instance of a given class
To test that an object was constructed by a given constructor function, use jasmine.any(Klass)
:
describe('plus()', function() {
it ('returns a number', function() {
let result = plus(1, 2)
expect(result).toEqual(jasmine.any(Number))
})
})
Understanding SQL compatibility modes in MySQL and MariaDB
MySQL and MariaDB have an SQL mode setting which changes how MySQL behaves.
The SQL mode value is comprised of multiple flags like "STRICT_TRANS_TABLES, NO_ZERO_IN_DATE"
. Each flag activates or disables a particular behavior.
The default SQL mode varies widly between versions of MySQL and MariaDB. In general, more recent versions of MySQL and MariaDB have stricter settings than older versions, and MySQL has stricter settings than the more liberal MariaDB.
If your app explodes ...
How to set up SMTP email delivery with a Gmail account
If you want to make your Rails application be capable of sending SMTP emails, check out the action mailer configuration section in the Ruby on Rails guide.
TL;DR you will end up having an smtp_settings
hash that looks something like this:
smtp_settings = {
address: ...,
domain: ...,
port: ...,
user_name: ...,
password: ...,
authentication: ...,
tls: ...,
enable_starttls_auto: ...,
}
This hash can be set as the `delivery_me...
Effectively Using Materialized Views in Ruby on Rails · pganalyze
It's every developer's nightmare: SQL queries that get large and unwieldy. This can happen fairly quickly with the addition of multiple joins, a subquery and some complicated filtering logic. I have personally seen queries grow to nearly one hundred lines long in both the financial services and health industries.
Luckily Postgres provides two ways to encapsulate large queries: Views and Materialized Views. In this article, we will cover in detail how to utilize both views and materialized views within Ruby on Rails, and we can even take...
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.
Howto: Change the keyboard shortcut for the emoji-picker
Im using the terminator terminal with the keyboard shortcut Control+Shift+E for splitting the terminal. I got used to this shortcut.
Yesterday the Ubuntu update seems to have upgraded ibus
, which got this emoji picker that also uses Control+Shift+E to open.
You can change this behaviour by opening the ibus setup from the console:
ibus-setup
A window will open and you can delete the shortcut in the emoji
tab (Emoj...