This card describes different flavors for concatting HTML safe strings in a helper method in Rails. You might want to use tag helper instead of content_tag (the tag
helper knows all self closing tags).
def navigation_with_html_safe
outer_html = ''.html_safe
outer_html <...
Tests are about 100% control over UI interaction and your test scenario. Randomness makes writing tests hard. You will also push tests that are green for you today, but red for a colleague tomorrow.
That said, please don't do something like this:
Factory(:document) do |document|
document.category { ['foo', 'bar', 'baz'].sample }
end
Instead do this:
Factory(:document) do |document|
document.category 'foo'
end
I even recommend to not use libraries like [Faker]...
One of the earliest pieces of wisdom we are given as programmers is to not write duplicate code: Don’t Repeat Yourself (or DRY if you prefer). Identical blocks of code to set up a test sure does look like repetition, so we extract it into a before block.
This is a mistake for tests.
The article explains about how sharing setup between examples make test files harder to read and evolve.
A related frustration I have is working on ultra-DRY & betterspecs-like ...
The following two hints are taken from Github's Ruby style guide:
If your regular expression mentions a lot of forward slashes, you can use the alternative delimiters %r(...)
, %r[...]
or %r{...}
instead of /.../
.
%r(/blog/2011/(.*))
%r{/blog/2011/(.*)}
%r[/blog/2011/(.*)]
If your regular expression is growing complex, you can use the /x
modifier to ignore whitespace and comments or use named groups or...
TLDR: In tests you need to clean out the database before each example. Use :transaction
where possible. Use :deletion
for Selenium features or when you have a lot of MyISAM tables.
You want to clean out your test database after each test, so the next test can start from a blank database. To do so you have three options:
DatabaseCleaner.strategy = :transaction
or `config.use_transactional_fi...Regular expressions in Javascript are represented by a RegExp
object. There also is a regex literal as in many other languages: /regex/
. However, they are used slightly differently.
/foo+/
RegExp("foo+")
or new RegExp("foo+")
RegExp("\\d+")
HTML <video>
elements can automatically start playing when the autoplay
attribute is set on them. Except for when they can not, e.g. on pageload, or when the element enters the DOM without user interaction, or when the browser for some other reason decided to not start playing the video.
While there is no native "autoplay failed" event to listen to, you can wait for video data to be loaded and then check if the video actually started playing.
<video autoplay>
<source src="example.mp4" type="video/mp4" />
</video>
...
Debugging performance issues in your Rails app can be a tough challenge.
To get more detailed insights consider using the rack-mini-profiler gem.
Add the following gems:
group :development do
gem 'memory_profiler'
gem 'rack-mini-profiler'
gem 'stackprof'
end
Unpoly will interfere with the rack-mini-profiler widget, but configuring the following works okayish:
// rack-mini-profiler + unpoly
if (process...
There are two ways a logout in SAML can happen: Service Provider (SP) initiated and Identity Provider (IDP) initiated logout. I'll explain how to implement both flows with devise_saml_authenticatable
.
Note
SAML also supports a
SOAP
and anArtifact
binding to do this. This guide only refers toPOST
andRedirect
bindings.devise_saml_authenticatable
does not supportSOAP
andArtifact
bindings.
When the user clicks on Logout
within the app, the app can trigger...
Starting with Rails 7.1 the production logger is set to standard out. For applications running with opscomplete ensure to keep logging to a file as before (e.g. when running bin/rails app:update
).
It should be enough to change these lines in the config/environments/production.rb
back to the implementation in Rails <7.1:
- # Log to STDOUT by default
- config.logger = ActiveSupport::Logger.new(STDOUT)
- .tap { |lo...
Note
Using rem only ever makes sense when the root font size is dynamic, i.e. you leave control to the user. Either by a) respecting their user agent defaults, or by b) offering multiple root font sizes in your application.
By defining @media queries in rem, they will accommodate to the root font size of your page. At a larger root font, breakpoints will be at larger widths, scaling with the font. However, there is a catch in case b) mentioned in the note above.
Relative length units in media queries are based on the initial value,...
If you are using git submodules in Gitlab CI, you might run into a "The project you were looking for could not be found or you don't have permission to view it."
Gitlab added a feature that new projects are no longer allowed to be cloned inside CI runs of other repositories by default. To fix this
The standard way to abort async code is that your function takes a AbortSignal
{ signal }
property. The caller can use this signal to send an abort request to your function. Upon receiving the request, your function should reject its promise with an error.
Async browser functions like fetch()
reject their promises with a new DOMException('Message here', 'AbortError')
when canceled.
This already has good browser support and can be polyfilled on older browsers.
Turns out, Cucumber::MultilineArgument::DataTable#diff!
caches some stuff. Code of the following form will not work as intended:
Then('some table should look like') do |expected_table|
patiently do
actual_table = calculate_actual_table
expected_table.diff!(actual_table) # not actually patient, will keep failing if it failed the first time
end
end
Instead, simply use
expected_table.dup.diff!(actual_table)
Developing or debugging SAML functionality can be a hassle, especially when you need to go back and forth with someone external who is managing the identity provider (IDP).
But you can setup a local keycloak server to act as your IDP to play around with. This might seam intimidating, but is actually quite simple when using docker and turning off some verification steps.
`mkdir -p keycloak_data && docker run --network=host -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN...
If you need to make an HTTPS connection to a host which uses an expired certificate, do not disable certificate verifications entirely. Doing that enables e.g. man in the middle attacks.
If you accept only a single expired and known certificate, you are much less in trouble.
All the solutions described below use a verify_callback
for the request's OpenSSL::X509::Store
where you can specify a lambda to adjust its verification response.
Your callback must return either true
or false
and OpenSSL's verification result is...
Due to network or hardware failures, it can happen that one of your cronjobs will not run at the time you specify in the schedule. Your code should be built in a way that it can be re-run at a later time (when the failure is resolved).
For example, if you are synchronizing data with another service once every day, your cronjob should not only synchronize changes from the last 24 hours. If you do this and a network failure will delay the execution of your job by 5 hours, you will only synchronize changes from hour 6-29, but forget change...
This card existed before, but was outdated due to browser implementation changes. The information below is validated for the current list of browsers we support.
By default your html
and body
elements are only as high as the actual page content inside their container. If you only have two lines of text in your page, your html
and body
elements will only be around 40 pixels high, regardless of the size of your browser window.
You might be surprised by this, since setting a background
on either html
and `body...
We already know that that we can create strings using the percent notation:
%(<foo="bar's ton">)
is perfectly fine Ruby.
But there is more. The curly brackets ({}
) are interchangable with most unicode characters (e.g. square brackets[]
).
Furthermore, you can add a "modifier" to the percent notation to control the return type of th...
Often people need links which are not linked directly, but should trigger execution of JavaScript.
You can find a lot of workarounds for that:
<a href="#">Do something with js!</a>
This defines an empty anchor. This may lead the browser to let the page jump to the top when the link is clicked, unless you call preventDefault
on the event. This is probably not what you want.
<a href="#!">Do something with js!</a>
This tells the browser to jump to an anchor !
. It depends on the browser implementation wha...
When building an application that sends e-mails to users, you want to avoid those e-mails from being classified as spam. Most obvious scoring issues will not be relevant to you because you are not a spammer.
However, your application must do one thing by itself: When sending HTML e-mails, you should include a plain-text body or tools like SpamAssassin will apply a significant score penalty. Here is how to do that automatically.
premailer-rails
to your Gemfile
and bundle
.There are several tools for DNS debugging which offer you more or less information. Most of the time the more simple ones, like host
oder nslookup
will be sufficient.
host
simple DNS lookup utility.
>host heise.de
heise.de has address 193.99.144.80
heise.de has IPv6 address 2a02:2e0:3fe:1001:302::
heise.de mail is handled by 10 relay.heise.de.
nslookup
query Internet domain name servers. Nslookup has two modes: interactive and non-interactive.
>nslookup heise.de
Server: 146.254.160.30
Address: 146.254.160.3...
Rewrote most of the card.
The RSpec matcher tests if two HTML fragments are equivalent. Equivalency means:
You use it like this:
html = ...
expect(html).to match_html(<<~HTML)
<p>
Expected content
</p>
HTML
You may override options from CompareXML by passing keyword arguments after the HTML string:
html = ...
expect(html).to match_html(<<~HTML, ignore_text_nodes: true)
...