Updated: Automated "git bisect" will make your day
Added methods to keep the line number steady while you time-travel between commits:
- Copy the file to a new location that is not tracked by Git
- Run RSpec example by description
- Run RSpec example by nesting index
How to create a terminal progress indicators in Ruby
For long running scripts it is useful to show a indicator for the progress in the terminal. Alternatively you can use a gem like paul/progress_bar.
count = User.count
index = 0
User.find_each do |user|
printf("Progress: %.2f%%\r", index.to_f / count * 100)
user.update!(role: 'member')
index += 1
end
Preview video
Updated: Jasmine: Creating DOM elements efficiently
I have moved away from creating fixture elements using CSS selectors. While CSS can be very concise, it can be hard to recognize the created elements, and how they are nested within each other.
A more visual alternative is to embed a string of HTML into your test. My specs often have a function htmlFixtures()
that parses the HTML and returns a reference to all created elements:
let [list, item1, item2] = htmlFixtures(`
<ul type="square">
<li>item 1</li>
<li>item 2</li>
</ul>
`)
Because the effective HTML is visible...
How to automatically optimize SVG files with esbuild
SVG files often contain redundant information, like editor metadata or hidden elements. When esbuild handles your static assets, you can easily optimize SVG files using svgo as a plugin. Here is how to do it.
Adding svgo as an esbuild plugin
- Add the
svgo
package to your project'spackage.json
- Adjust your
esbuild.config.js
like so:
const esbuild = require('esbuild')
const svgo = require('svgo')
const options = {
// ...
loader: {
// ...
'.svg': 'copy', // this may be different...
Rails: Using PostgreSQL full-text search without a gem
PostgreSQL can cosplay as a full-text search engine. It doesn't have the features or fidelity of ElasticSearch or Algolia, but it's good enough if you just need to search and rank large volumes of text.
This card will teach you how to index, search and rank your Rails models in a PostgreSQL full-text index. We will do this without using any gems aside from ActiveRecord. While there are gems like pg_search or pg_fulltext, manual integration requires very...
RSpec: executing specs by example id (or "nesting index")
There are several ways to run a single spec. I usually copy the spec file path with the line number of the example and pass it to the RSpec binary: bin/rspec spec/models/user_spec.rb:30
(multiple line numbers work as well: :30:36:68
). Another is to tag the example with focus: true
or to run the example by matching its name.
In this card I'd like to ...
Rails: Overwriting default accessors
All columns of a model's database table are automagically available through accessors on the Active Record object.
When you need to specialize this behavior, you may override the default accessors (using the same name as the attribute) and simply call the original implementation with a modified value. Example:
class Poet < ApplicationRecord
def name=(value)
super(value.strip)
end
end
Note that you can also avoid the original setter and directly read/write from/to the instance's attribute storage. However this is dis...
How to not die with ActionView::MissingTemplate when clients request weird formats
When HTTP clients make an request they can define which response formats they can process. They do it by adding a header to the HTTP request like this:
Accept: application/json
This means the client will only understand JSON responses.
When a Rails action is done, it will try to render a template for a format that the client understand. This means when all you are HTML templates, a request that only accepts application/json
will raise an error:
An ActionView::MissingTemplate occurred in pages#foo:
Missing templa...
Flexbox: flex-basis vs. width vs. min-width vs. max-width
Within a Flexbox layout, there are multiple CSS attributes that may affect a child's basis (the initial width before flexing). You might be confused how flex-basis
, width
, min-width
and the intrinsic width of your content play together.
The attached article explains the differences. In summary:
- If a
flex-basis
is set, that is used as the basis - If no
flex-basis
is set, thewidth
is used as the basis - If neither
flex-basis
norwidth
is set, the content...
HTML forms with multiple submit buttons
Most forms have a single submit button that will save the record when pressed.
Sometimes a form needs additional submit buttons like "accept" or "reject". Such buttons usually attempt a state transition while updating the record.
To process a form with multiple buttons, your server-side code will need to know which button was pressed. To do so you can give each submit button a different [formaction]
attribute. This will override the ...
Rails routing: Using constraints to avoid "Missing template" errors
You can use constraints in your routes.rb
to avoid getting ActionView::MissingTemplate
errors when wrong routes are called. Instead, the user will see a 404.
If you want multiple routes to use the same constraint you can use the block syntax:
constraints(format: 'html') do
resources :pages
resources :images
end
If you want constraints only on certain routes, you can do:
get '/users/account' => 'users#account', constraints: { format: 'html' }
Tip
You can also avoid this error type through [format con...
Haml Whitespace Preservation (or: Fixing Textarea Indentation in Haml)
Haml renders HTML with indentation reflecting the nesting level of elements. When it comes to white-space preserving content, this may become a problem: the content will be rendered including the HTML indentation.
Problematic: Preserved Indentation
.nest
%span Reference
%pre
= content
<div class="nest">
<span>Reference</span>
<pre>
Hello
World
</pre>
</div>
Better: Without Extra Indentation
Render with tilde ~
instead of equal...
Why your Cucumber feature loses cookies when run under Selenium
When your Cucumber feature seems to forget cookies / sessions when you run it with Selenium check if the test travels in time like here:
Given the date is 2017-10-20
When I sign in
Then I should see "Welcome!"
What happens here is that the Rails application serving pages runs in 2017, but the process running your browser still lives today. This huge gap in time will expire most cookies immediately.
If all you need is to freeze the time to a date, a workaround is to travel to the future instead.
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
...
Git: Restore
tl;dr
git checkout
is the swiss army of git commands. If you prefer a semantically more meaningful command for restoring tasks, usegit restore
instead.With this command you can ...
- ... do unstaging -
git restore --staged
- ... discard staged changes -
git restore --staged --worktree
- ... discard unstaged changes -
git restore
- ... restore deleted files -
git restore
- ... restore historic versions -
git restore --source
- ... recreate merge conflicts -
git restore --merge
- ... specifiy...
Capybara: Working with invisible elements
When Capybara locates elements in the DOM, by default it allows only accessing visible elements -- when you are using a driver that supports it (e.g. Selenium, not the default Rack::Test
driver).
Consider the following HTML:
<div class="test1">One<div>
<div class="test2">Two</div>
With some CSS:
.test1 { display: block }
.test2 { display: none }
We will be using Capybara's find
below, but this applies to any Capybara finder methods.
Default: visible: :visible
As described above, by default Capybara finds ...
Defining and calling lambdas or procs (Ruby)
Ruby has the class Proc
which encapsulates a "block of code". There are 2 "flavors" of Procs
:
- Those with "block semantics", called
blocks
or confusingly sometimes alsoprocs
- Those with "method semantics", called
lambdas
lambdas
They behave like Ruby method definitions:
- They are strict about their arguments.
-
return
means "exit thelambda
"
How to define a lambda
-
With the
lambda
keywordtest = lambda do |arg| puts arg end
-
With the lambda literal
->
(since Ruby 1.9.1)
...
ActiveStorage: How to add a new preprocessed named version
Given there is a user with an attachable avatar:
class User < ApplicationRecord
has_one_attached :avatar
end
If you want to add a preprocessed version follow these steps:
- Add the named version and deploy
class User < ApplicationRecord
has_one_attached :avatar do |attachable|
attachable.variant :preview, resize_to_fit: [177, 177 * 9 / 16], preprocessed: true
end
end
- Preprocess this version for all existing records `bundle exec rails runner 'User.find_each { |user| user.avatar.variant(:preview).proc...
ActiveStorage: How to copy / clone an attachment from one record to another
Given there is a user with an attachable avatar:
class User < ApplicationRecord
has_one_attached :avatar
end
You can copy the avatar from one user to another user with the code below:
user_1 = User.first
user_2 = User.create!(
avatar: {
io: StringIO.new(user_1.avatar.download),
filename: user_1.avatar.blob.filename.to_s,
content_type: user_1.avatar.blob.content_type.to_s,
}
)
Note: For large attachments you might need to use a different approach to avoid memory issues.
Using Low-Level Prompts for High-Accuracy AI Coding
The key to unlocking the full potential of LLMs in coding lies in crafting precise prompts. The main challenge is learning how to structure prompts effectively to guide the model toward accurate results. Further evidence supporting this is the fact that Aider already writes ~70% of its own code (as of 02/2025). However, when starting out, your results may fall short of efficiently generating large portions of your code with the...
Git commands to discard local changes
Use case
You have uncommited changes (you can always check by using git status
), which you want to discard.
Context
Now there are several options to discard these depending on your exact situation.
The headlines will differentiate the cases whether the files are staged or unstaged.
- Staged and unstaged changes
- [Staged changes](https://makandracards.com/makandra/516559-git-commands-to-discard-local-changes#s...
RSpec: Tagging examples and example groups
In RSpec you can tag examples or example groups with any tags you like simply by saying
describe ReportCreator, slow: true do
# ..
end
describe ReportCreator do
it 'generates reports', slow: true do
# ...
end
end
You can then only run examples with these tags.
rspec --tag slow
rspec -t slow
# Using the parallel_tests gem
rake "parallel:spec[,,--tag slow]"
Or you can run all examples except the ones with a certain tag:
rspec --tag ~slow # note the ~
rspec -t ~slow
# Using the parallel_tests gem
r...
PSA: "index: true" in Rails migrations does not work as you'd expect
Several Rails migration methods accept index: true
as an option to create an index. In some cases (like #add_column
), this option is silently discarded. Know what you are doing, or use #add_index
instead.
Example
Consider the following migration.
class CreateExamples < ActiveRecord::Migration
def change
create_table :examples do |t|
t.references :category, index: true
t.boolean :positive, index: true
t.integer :number_of_participants, index: true
end
add_reference :examples, :user, index: tr...