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: 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.
Ruby: Generating and parsing JSON, or: understanding JSON::ParserError "unexpected token"
json
is part of the standard library of Ruby and deals with JSON, obviously. As you know, JSON is the string format that represents simple data structures. Ruby data structures that resemble Javascript objects can be serialized to JSON with #to_json
. These can be restored from a JSON string with JSON.parse()
.
So what could go wrong here?
JSON.parse("a".to_json)
It will raise JSON::ParserError (784: unexpected token at '"a"')
. But why?
Generating JSON vs serializing objects
J...
Geordi 5.4.0 released
5.4.0 2021-02-01
Compatible changes
- Add
geordi branch
command that checks out a feature branch based on a story from Pivotal Tracker - Faster MySQL dumping with
--single-transaction
and--quick
- Allow pivotal tracker ids in the global config file
- Fix missing require for
Fileutils
in the dump load command (#145) - Document
PARALLEL_TEST_PROCESSORS
Parsing JSON with edge cases
The linked article shows that there are unclear parts in the JSON specification and that different parsers treat them differently (which could lead to security vulnerabilities in certain cases).
I was curious what Ruby does (Ruby 2.6.6 with gem json 2.3.0, implementing RFC 7159):
Duplicate Keys
irb(main):001:0> require 'json'
=> true
irb(main):002:0> JSON.parse('{"qty": 1, "qty": -1}')
=> {"qty"=>-1}
Character Collision
irb(main):009:0> JSON.parse('{"qty": 1, "qty\ud800": -1}')
JSON::ParserError (487: incomplete sur...
Webmock < 3.12.1 cannot handle IPv6 addresses correctly
We had the issue, that a VCR spec failed, after updating CarrierWave
from version 0.11.0
to 1.3.2
.
In this version, CarrierWave
uses the gem SsrfFilter
, which retrieves the IP addresses for the given hostname and replaces the hostname in the requested url with one of them.
It works with IPv4 addresses, but not with IPv6 addresses, because WebMock cannot handle those correctly:
uri = "#{protocol}://...
Making ZSH the default shell on Ubuntu 20.04
ZSH is an alternative command line shell that includes some features like spelling correction, cd automation, better theme, and plugin support. You can replace Bash with ZSH like following:
sudo apt-get install zsh
Setting ZSH as default login shell
sudo usermod -s /usr/bin/zsh $(whoami)
Opening a new terminal window will show you a dialog where you can configure your initial ZSH config (Option 2 recommended).
Afterwards you can install the plugin manager Oh-My-ZSH and select a prop...
Mixed Content Examples
The pages […] allow you to see different types of mixed content and test how they behave in your browser. The "Secure" pages are referencing assets with HTTPS, the "Non-Secure" pages are referencing them with HTTP. Generally, you'll observe the same behavior with both Secure pages and the Secure HTTP page for a given test; the behavior will change on the Non-Secure HTTPS page.
Also see Testing HTTPS with badssl.com.
Rails: Parsing a time in a desired timezone
Sometimes you want to have a time in a given timezone independent from you Rails timezone settings / system timezone. I usually have this use case in tests.
Example
Time.parse('2020-08-09 00:00')
will return different results e.g. 2020-08-09 00:00:00 +0200
depending on the Rails timezone settings / system timezone. But in this example we always want to have the given time in UTC because that's what the API returns.
it 'returns a valid API response', vcr: true do
expect(client.get('/users/1')).to have_attributes(
name: 'So...
How to fix: WrongScopeError when using rspec_rails with Rails 6.1
tl;dr: Upgrade the gem to at least 4.0.1
When you use rspec_rails
in a version < 4 with Rails 6.1 you may encounter an error like this:
Failure/Error:
raise WrongScopeError,
"`#{name}` is not available from within an example (e.g. an " \
"`it` block) or from constructs that run in the scope of an " \
"example (e.g. `before`, `let`, etc). It is only available " \
"on an example group (e.g. a `describe` or `context` block)."
`name` is not available from within an example (e.g. an `it` block) or from constructs that...
Best practices for REST API design
A rough guide how to implement a REST API.
The discussion here includes some interesting points as well:
- Timestamps: ISO8601 format ("2021-02-22T20:34:53.686Z")
- Google API guideline: https://google.aip.dev/
- Numbers: String vs. Number
The JSON number type is not a double. It's just a number of arbitrary size and precision in integer/decimal/E format that can be parsed as whatever the parser finds fitting.
- Pagination: Limit + Offset vs. Object ID / Pointer vs. System-Version...
Running old ImageMagick versions in a Docker container
If your project depends on an old version of ImageMagick that you can no longer install in your system, you can choose the run an old ImageMagick in a Docker container.
Dockerized ImageMagick commands will only work with absolute path arguments. You need to boot a corresponding docker container once before using it.
Setting up Docker
If you haven't installed Docker yet, use our guide or the [official instructions](https://docs.docker.com/get-started/...
Using ActiveRecord with threads might use more database connections than you think
Database connections are not thread-safe. That's why ActiveRecord uses a separate database connection for each thread.
For instance, the following code uses 3 database connections:
3.times do
Thread.new do
User.first # first database access makes a new connection
end
end
These three connections will remain connected to the database server after the threads terminate. This only affects threads that use ActiveRecord.
You can rely on Rails' various clean-up mechanisms to release connections, as outlined below. This may...
Make your Rails console (and irb) output better readable
Pour color on your Rails console with awesome_print. Turn confusing long strings into formatted output. Have objects and classes laid out clearly whenever you need it.
Put gem 'awesome_print', :group => :development
into your Gemfile. Now on the Rails console you have the command ap
that will give you a colored, formatted output of whatever you pass it. See the example output of the User
class below.
For customization visit the repository on Github.
 and place your service definitions under the `services` key, or omit the `version` key and place your service definitions at the root of the file to use version 1.
For more on the Compose file format versions, see https://docs.docker.com/compose/compose-file/
...
WYSIWYG with Action Text
Rails 6 includes a WYSIWYG editor, Action Text. It works out of the box quite well, but chances are that you want to add some custom functionality. This card contains some tips how to achieve this.
Setup
Basically, follow the guide in the Rails documentation. The automated script may not work with the way webpacker is configured in your project, but it should be easy to fix.
If you don't want the default c...
Rails: Postgres Partial Indexing
PostgreSQL has partial indexes. With a partial index you tell Postgres to only index rows matching a given query.
Some uses cases for a partial index:
- You want a uniqueness index, but only under some conditions
- Your table is very large and indexing every row becomes expensive
The linked article shows how to create a partial index with Rails.