Sentry: Different ways of deferring notifications for an issue
We use Sentry to be informed about different kinds of issues. One of the key features is that you are not getting spammed if many errors of the same kind occur in a small timespan.
If an issue pops up the usual workflow is to fix the code and mark the issue as "resolved" in Sentry. Only new or resolved issues trigger another email notification when they are proxied through Sentry.
This workflow does not fit well for issues we cannot fix, e.g. when consuming an external API that is sometimes down. In such cases you ...
Automatically validating dependency licenses with License Finder
"Open-source software (OSS) is great. Anyone can use virtually any open-source code in their projects."
Well, it depends. Licenses can make things difficult, especially when you are developing closed-source software. Since some OSS licenses even require the employing application to be open-sourced as well (looking at you, GPL), you cannot use such software in a closed-source project.
To be sure on this, we have developed a project-level integration of Pivotal's excellent [license_finder](https:/...
ActiveRecord: String and text fields should always validate their length
If you have a :string or :text field, you should pair it with a model validation that restricts its length.
There are two motivations for this:
- In modern Rails, database types
:stringand:textno longer have a relevant size limit. Without a validation a malicious user can quickly exhaust the hard drive of your database server. - In legacy Rails (or database schemas migrated from legacy Rails), database types
:stringand:texthad a database-side length constraint. When the user enters a longer string, the ActiveRecord valida...
How to prevent Nokogiri from fixing invalid HTML
Nokogiri is great. It will even fix invalid HTML for you, like a browser would (e.g. move block elements out of parents which are specified to not allow them).
>> Nokogiri::HTML.fragment("<h1><p>foo</p><span>bar</span></h1>").to_s
=> "<h1></h1><p>foo</p><span>bar</span>"
While this is mostly useful, browsers are actually fine with a bit of badly formatted HTML. And you don't want to be the one to blame when the SEO folks complain about an empty <h1>.
To avoid said behavior, use Nokogiri::XML instead of Nokogiri::HTML whe...
FactoryBot: Traits for enums
FactoryBot allows to create traits from Enums since version 6.0.0
The automatic definition of traits for Active Record enum attributes is enabled by default, for non-Active Record enums you can use the traits_for_enum method.
Example
factory :user do
traits_for_enum :role, %w[admin contact] # you can use User::ROLES here, of course
end
is equivalent to
factory :user do
trait :admin do
role { 'admin' }
end
trait :contact do
role { 'c...
The HTML5 video element
# Basic HTML example
<video poster="preview_image.png" controls>
<source src="or_here.webm" type="video/webm" />
<source src="alternative_if_browser_cant_pay_first_source.mp4" type="video/mp4" />
<track src="optional_subtitles.vtt" kind="subtitles" srclang="de" label="Deutsch" default>
</video>
# Javascript API (notable methods and properties)
video = document.querySelector('video')
video.play()
video.pause()
video.load() // Reset to the beginning and select the best available source
video.currentSrc // The selected source
video.c...
HTTP Client in RubyMine
RubyMine has a HTTP Client that can be useful to test web APIs.
Just create a .http scratch file an write your request in it.
The request can then be executed with the "Run all requests in File" button above the file.
Some alternatives:
The format for request is like this:
Method Request-URI HTTP-Version
Header-field: Heade...
How to use Active Job to decouple your background processing from a gem
In a web application you sometimes have tasks that can not be processed during a request but need to go to the background.
There are several gems that help to you do that, like Sidekiq or Resque.
With newer Rails you can also use ActiveJob as interface for a background processing library. See here for a list of supported queueing adapters.
For ...
Testing for XSS in Markdown Fields
If you render markdown from user input, an attacker might be able to use this to inject javascript code into the source code of your page.
The linked github page is a collection of common markdown XSS payloads which is handy for writing tests.
Producing arbitrary links:
[Basic](javascript:alert('Basic'))
[Local Storage](javascript:alert(JSON.stringify(localStorage)))
[CaseInsensitive](JaVaScRiPt:alert('CaseInsensitive'))
[URL](javascript://www.google.com%0Aalert('URL'))
[In Quotes]('javascript:alert("InQuotes")')
Using onload...
Error handling in DOM event listeners
When an event listener on a DOM element throws an error, that error will be silenced and not interrupt your program.
In particular, other event listeners will still be called even after a previous listener threw an error. Also the function that emitted the event (like element.dispatchEvent() or up.emit()) will not throw either.
In the following example two handlers are listening to the foo event. The first handler crashes, th...
The JavaScript Object Model: Prototypes and properties
Speaker today is Henning Koch, Head of Development at makandra.
This talk will be in German with English slides.
Introduction
As web developers we work with JavaScript every day, even when our backend code uses another language. While we've become quite adept with JavaScript at a basic level, I think many of us lack a deep understanding of the JavaScript object model and its capabilities.
Some of the questions we will answer in this talk:
- How does the
newkeyword construct an object? - What is the differen...
Cucumber may complain about cucumber.yml being invalid when it is valid
Running Cucumber tests while your cucumber.yml is 100% valid may still produce the following error.
cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.
This may in fact be due to your rerun file (e.g. tmp/rerun.txt) being invalid. Delete it and try again.
Legacy CarrierWave: How to generate versions with different file extensions
We use CarrierWave in many of our projects to store and serve files of various formats - mostly images. A common use case of CarrierWave's DSL is to "process" the original file in order to create multiple "versions", for example different resolutions of the same image.
Now we could go one step further: What if we want to create versions that have a different file extension than the original file? For example, let's assume we'd like to create a ve...
Ruby: Referencing global variables with the built-in English library
tl;dr
Don't forget
require 'English'if you use a named global such as$LAST_MATCH_INFO. Otherwise this could result in an annoying bug.
With Ruby's build-in library English you can reference global variables with an english name. This makes you code easier to read and is also suggested by Rubocop's Style/GlobalVars cop.
Example before:
if 'foo' =~ /foo/
puts $~[1] # => foo
end
Example af...
Rspec: How to write better specs
betterspecs.org is a documentation on how to write better RSpec tests.
Note that there are also other approaches like The Self-Contained Test, which is complementary to the dry-approches in betterspecs. Like usual you need to weight the different recommendation and there is no rule of thumb for all specs.
How to reset a Mock
With Rspec you can mock objects or functions, for example like this:
expect(my_object).to receive(:my_function).and_return('hello world')
It's also easy to remove mocks for an object:
RSpec::Mocks.space.proxy_for(my_object).reset
whenever: Installing cron jobs only for a given Rails environment or Capistrano stage
We use the whenever gem to automatically update the crontab of the servers we deploy to. By default, whenever will update all servers with a matching role (we use the :cron role ).
This card describes how to install some tasks only for a given Rails environment or for a given Capistrano stage ("deployment target").
Installing jobs only for a given Rails environment
-----------------------------------...
The Self-Contained Test
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 ...
Rspec: Expecting a Rake task to be called
This seems to be obvious, but you can expect Rake tasks to be called in RSpec.
it 'deletes all Users' do
FactroyBot.create(:user)
expect(Rake::Task['notify:critical_operation']).to receive(:invoke)
expect { described_class.clean }.to change(User, :count).from(1).to(0)
end
Note: Try to avoid logic in rake tasks and prefer to just call classes in them.
Example:
desc 'Some task'
task :some_task do
SomeClass.new.run
end
How to use git fixup
Using git fixup helps you to speed up appending changes further back in the git history of your feature branch.
Example:
git commit --fixup aabbcc # Create a commit with the message "fixup! Commit message of aabbcc"
git rebase -i --autosquash master
It would be nice if you could use this feature without the -i flag, but until now it seems not to be possible. Read more about our recommended git workflow for feature branches.
Also have a look at [git shortcut to use git fixup](https://makandracards.com/makand...
How to evaluate CSS media queries in JavaScript
To make CSS rules dependent on the screen size, we use media queries:
@media (max-width: 500px) {
// rules for screen widths of 500px or smaller
}
Browsers will automatically enable and disable the conditional rules as the screen width changes.
To detect responsive breakpoints from JavaScript, you may use the global matchMedia() function. It is supported in all brow...
Rubygems: Installing the last version of rubygems that has no rubyforge_project deprecation warning
You can install rubygems 3.0.8 (released on February 18, 2020) to keep all the Gem::Specification#rubyforge_project deprecation warnings away from your development log. With Rubygems >= 3.1 this deprecation warning was introduced. While maintaining older projects this could get quite annoying and the fix below might okey, for newer projects the right ways is to upgrade the gems.
gem update --system 3.0.8
Example message:
NOTE: Gem::Specification#rubyforge_project= is deprecated with no replacement. It will be removed o...
Git: How to add changes matching a regular expression
When you have many changes, and you want to spread them across different commits, here is a way to stage all changes matching a given regular expression for a single commit.
Example
Consider the following git diff output.
diff --git a/file1.rb b/file1.rb
index 806ca88..36d536b 100644
--- a/file1.rb
+++ b/file1.rb
@@ -1,7 +1,5 @@
-# Here is a useless comment.
-# It will be removed.
class File1
- def foo
+ def bar
# ...
end
end
diff --git a/file2.rb b/file2.rb
index 550e1c6..600f4e3 100644
--- a/file2.rb
+++ b/file2...
Five years of "Today I Learned" from Josh Branchaud
The linked GitHub repository is a bit like our "dev" cards deck, but groomed from a single person (Josh Branchaud). It includes an extensive list of over 900 TILs on many topics that might be interesting for most of us. (e.g. Ruby, Rails, Git, Unix..)
Ruby
Here is an excerpt of all the Ruby TILs that were new to me. I encourage you to take your time to skim over the original list as well!
-
Assoc For Hashes
- `Hash#ass...