Clean code: Avoiding short versions in command options
This card is a general reminder to avoid the short version of a command option in shared code. It's much easier to understand a command and search for an option when it's written out.
You can still use the short version of the options in your own terminal or in code snippets that are more useful when they are very compact. For the latter case you often see a description of the command options one line below e.g. in posts on stackoverflow.
Example good (in code):
/usr/bin/gpg --output password.txt --decrypt password.txt.gpg
...
Bundler: Packaging gems into the git repository (offline installation)
Installing gems on a server that has no access to the internet (especially rubygems.org
) requires to bundle the gems into the repository itself. This requires to adjust the bundle config in the repository.
- Execute the following commands to configure bundler:
bundle config set --local path vendor
bundle config set --local disable_shared_gems true
Note
For Bundler < 2 you have to omit the "set":
bundle config --local name value
.
See here: [https://bundler.io/v1.17/man/bundle-config.1.html](https://bundler.io/v1.17/man...
How to generate and test a htpasswd password hash
Generate a password
htpasswd -Bn firstname.lastname
This will ask you for a password and use bcrypt (-B
, more secure) and print the output to stdout (-n
).
Check if password matches the hash
You'll first have to write the password hash to a file:
echo firstname.lastname:$2y$05$4JXxd2GM/J2...9c3KJmFS > htpass_test
Check, if it is correct:
htpasswd -v htpass_test firstname.lastname
You probably should not use the -b
switch to read the password from the command line as the password will then be visible...
Do not pass an empty array to ActiveRecord.where when using NOT IN
Be careful with the Active Record where
method. When you accidentally pass an empty array to the where
method using NOT IN
, you probably will not get what you expected:
User.where("id NOT IN (?)", [])
=> SELECT `users`.* FROM `users` WHERE (id NOT IN (NULL))
Even though you might expect this to return all records, this actually results none.
Never use the expression id NOT IN (?)
without taking care of this case! See below some workarounds.
Rails < 4
Rails < 4 does not provide a pretty workaround.
ids = ...
Emulating document.currentScript in old browsers
When you need the DOM node of a <script>
tag (e.g. to read extra attributes, or to modify the DOM near it), you can usually reference it via document.currentScript
.
However, document.currentScript
is unsupported in ancient browsers, like Internet Explorer 11 or wkhtmltopdf's Webkit engine.
If you are not running async scripts, you can easily polyfill it:
document.scripts[document.scripts.length - 1]
It works because document.scripts
grows with each <script>
tag that was evaluated.
That is also the reason why th...
Capistrano: Deployment issue undefined method `[]' for nil:NilClass
In newer passenger versions the output of passenger -v
has changed. capistrano-passenger
tries to parse the version and now causes the error undefined method '[]' for nil:NilClass
. To fix this you only need to upgrade the capistrano-passenger
gem.
Therefore run bundle update capistrano-passenger --conservative
.
The version change of passenger from 6.0.7
to 6.0.8
has triggered this problem. This is fixed in capistrano-passenger >= 0.2.1
.
Getting permanent links to files on Github or Gitlab
Please don't simply copy line number links from Github. The URL usually contains a branch name like master
which will change over time:
https://github.com/makandra/upjs/blob/master/lib/assets/javascripts/up/link.js.coffee#L76
If someone now posts an insertion or deletion to that file into master
your link points to the wrong line!
A better way is to press the Y
key after clicking on a line number. This will transform the URL to another URL that points to the particular commit:
https://github.com/makandra/upjs/blob/b3b14...
How to explain SQL statements via ActiveRecord
ActiveRecord offers an explain
method similar to using EXPLAIN
SQL statements on the database.
However, this approach will explain all queries for the given scope which may include joins
or includes
.
Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:
User.where(id: 1).includes(:articles).explain
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
+----+-------------+-------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-----...
The developer console can do more than you think!
You can do so much more than console.log(...)
! See the attached link for a great breakdown of what the developer console can give you.
Some of my favorites:
console.log takes many arguments
E.g. console.log("Current string:", string, "Current number:", 12)
Your output can have hyperlinks to Javascript objects
E.g. console.log("Check out the current %o, it's great", location)
[Di...
What does 100% mean in CSS?
The attached article examines what the percent unit (%
) is relative to in CSS
The article does a great job of visualizing the dependencies. The TLDR is:
Own property | % of |
---|---|
height |
parent height |
width |
parent width |
top |
parent height |
left |
parent width |
margin-top |
parent width |
margin-left |
parent width |
padding-top |
parent width |
padding-left |
parent width |
Using Passenger Standalone for development
For our production servers we use Passenger as a Ruby application server. While it is possible to use Passenger for development as an Apache module, the installation process is not for the faint of heart.
Luckily Passenger also comes as a standalone binary which requires zero configuration.
You can Passenger Standalone as a replacement for Webrick or Thin if you'd like to:
- Use SSL certificates locally
- Get performance behavior that is closer to ...
Converting ES6 to ES5 on the command line
I use the TypeScript compiler for this, since its output is more minimal than Babel's.
The following will transpile all src/*.js
files into a file build.js
:
npm install typescript
npx tsc src/*.js --target ES5 --allowJs --outFile build.js
The output will only transpile ES6 syntax. It will not include any polyfills for missing APIs.
Changes to positional and keyword args in Ruby 3.0
Ruby 3.0 introduced a breaking change in how it treats keyword arguments.
There is an excellent blog post on the official Ruby blog going into the details. You should probably read that, but here is a slightly abbreviated version:
What changed
When the last argument of a method call is a Hash, Ruby < 3 automatically converted it to to Keyword Arguments. If you call a method in Ruby >= 3 that accepts keyword arguments, eithe...
RubyMine: How to restore the Back to last position shortcut on Ubuntu 20.04
I really love to use the shortcuts CTRL
+Alt
+ Arrow Left
and CTRL
+Alt
+ Arrow Right
to navigate through the code. It worked great on Ubuntu 18.04 and MATE but after migrating to my new notebook with GNOME and Ubuntu 20.04, I realized that the shortcuts didn't work anymore. Well, it worked via Navigate > Back
and also showed the shortcut, but my fingers weren't able to do this...
I cried a lot. (Why God? WHY?)
Then I found this [thread on StackOverflow](https://stackoverflow.com/questions/47808160/intellij-idea-ctrlaltleft-short...
Ruby: How to convert hex color codes to rgb or rgba
When you have a hex color code, you can easily convert it into its RGB values using plain Ruby.
>> "#ff8000".match(/^#(..)(..)(..)$/).captures.map(&:hex)
=> [255, 128, 0]
You can use that to implement a simple "hex to CSS rgba value with given opacity" method:
def hex_color_to_rgba(hex, opacity)
rgb = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex)
"rgba(#{rgb.join(", ")}, #{opacity})"
end
>> hex_color_to_rgba("#ff8000", 0.5)
=> "rgba(255, 128, 0, 0.5)"
If you need to support RGBA hex color codes,...
Rails 4 introduced collection_check_boxes
Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes
. It behaves similar to #collection_select
, but instead of a single select field it renders a checkbox and a label for each item in the collection.
= form_for @post do |form|
= form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial
How generated form params look like
---------------------------------...
Capybara will not find links without an href attribute
Capybara will fail to find <a>
tags that are missing an href
attribute. This will probably happen to you every now and then on JavaScript-heavy applications.
An example would be an AngularJS application where the following HTML actually works. [1]
<a ng-click="hello()">Hello</a>
Capybara will fail to find that link, even though looking it up via the DOM shows it:
>> find_link("Hello")
Capybara::ElementNotFound: Unable to find link "Hello"
>> find("a").text
=> "Hello"
To make find_link
and click_link
work, ...
Online tool to convert tables between different formats
https://tableconvert.com/ is an online tool to convert tables between different formats (e.g. json, markdown, csv).
It also has a button to transpose a table ("rotate" it by 90 degree).
The tool can be handy if you have tests with large markdown tables for testing contents of a flat json structure or csv.
Please note that you should not use it with sensitive data (like all online tools in general).
Capybara: Preventing headless Chrome from freezing your test suite
We prefer to run our end-to-end tests with headless Chrome. While it's a very stable solution overall, we sometimes see the headless Chrome process freeze (or the Capybara driver losing connection, we're not sure).
The effect is that your test suite suddenly stops progressing without an error. You will eventually see an error after a long timeout but until then it will seem that your suite is frozen. If you're also using [capybara-screenshot](https:/...
Capybara: Waiting for pending AJAX requests after a test
When ending a Selenium test Capybara resets the browser state by closing the tab, clearing cookies, localStorage
, etc.
It may be a good idea to wait for all in-flight AJAX requests to finish before ending a scenario:
- You may have client-side JavaScript that freaks out when the tab closure kills their pending requests. If that JavaScript opens an error alert or spams errors to the console, your test may fail after the last step.
- With unlucky timing the server may receive an AJAX request as the browser tab closes, causing a connection ...
Capybara: Preventing server errors from failing your test
When your Rails application server raises error, Capybara will fail your test when it clears the session after the last step. The effect is a test that passes all steps, but fails anyway.
Capybara's behavior will help you to detect and fix errors in your application code. However, sometimes your application will explode with an error outside your control. Two examples:
- A JavaScript library references a source map in its build, but forgets to package the source map
- CarrierWave cleans up an upload or cache file after the record was delet...
Capybara: Pretending to interact with the document
Browsers blocks abusable JavaScript API calls until the user has interacted with the document. Examples would be opening new tab or start playing video or audio.
E.g. if you attempt to call video.play()
in a test, the call will reject with a message like this:
NotAllowedError: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
Workaround
To pretend document interaction in a test you can create an element, click on it, and remove the element again. This unblocks the entire JavaSc...
RSpec: How to test the content of a flash message in a request spec
The ActionDispatch module of Rails gives you the helper method flash
to access the flash messages in a response.
describe PostsController, type: :request do
describe 'update' do
it 'shows a success message on update' do
post_record = create(:post)
put "/posts/#{post_record.id}"
# Same as @request.flash[:alert]
expect(flash[:alert]).to eq('Post updated successfully.')
end
end
end
makandra/capybara-lockstep
capybara-lockstep can help you with flaky end-to-end tests:
This Ruby gem synchronizes Capybara commands with client-side JavaScript and AJAX requests. This greatly improves the stability of a full-stack integration test suite, even if that suite has timing issues.