Rails: Accessing helper methods from a controller
In Rails 5+ you can access a helper from a controller using the helpers method:
# Inside a controller action
helpers.link_to 'Foo', foo_path
In older Rails versions you can use view_context instead:
# Inside a controller action
view_context.link_to 'Foo', foo_path
Dynamic super-overridable methods in Ruby – The Pug Automatic
How a macro can dynamically define a method that can be overridden with super in the same class.
You can use the with_module_inheritance helper below if you want. It can be handy to make parts of a modularity trait super-able.
# ./lib/ext/module/with_module_inheritance.rb
#
# This macro allows you to define methods in a modularity trait that can be
# modified using the `super` keyword
# See https://thepugautomatic.com/2013/07/dsom/
module WithModuleInheritance
def with_module_inher...
Ruby object equality
TLDR
if you define a equality method for a class you must also implement
def hash.
Ruby has a lot of methods that have to do something with equality, like ==, ===, eql?, equal?. This card should help you differentiate between those and give you hints on how to implement your own equality methods in a safe manner.
Differences between the methods
for everyday use: ==
When you compare two objects in ruby, you most often see the use of foo == bar. By default the == operator inherits from Object and is impl...
Jasmine: Mocking ESM imports
In a Jasmine spec you want to spy on a function that is imported by the code under test. This card explores various methods to achieve this.
Example
We are going to use the same example to demonstrate the different approaches of mocking an imported function.
We have a module 'lib' that exports a function hello():
// lib.js
function hello() {
console.log("hi world")
}
export hello
We have a second module 'client' that exports a function helloTwice(). All this does is call hello() ...
Jasmine: Creating DOM elements efficiently
Jasmine specs for the frontend often need some DOM elements to work with. Because creating them is such a common task, we should have an efficient way to do it.
Let's say I need this HTML structure:
<ul type="square">
<li>item 1</li>
<li>item 2</li>
</ul>
This card compares various approaches to fabricating DOM elements for testing.
Constructing individual elements
While you can use standard DOM functions to individually create and append elements, this is extremely verbose:
let list = document.createElement('...
Jasmine: Cleaning up the DOM after each test
Jasmine specs that work with DOM elements often leave elements in the DOM after they're done. This will leak test-local DOM state to subsequent tests.
For example, this test creates a <spoiler-text> element, runs some expectations, and then forgets to remove it from the DOM:
describe('<spoiler-text>', function() {
it ('hides the secret until clicked', function() {
let element = document.createElement('spoiler-text')
element.secret = 'The butler did it'
document.body.appendChild(element)
...
Variable fonts: Is the performance trade-off worth it? - LogRocket Blog
Variable fonts are popular for two reasons: they expand design possibilities and improve website performance. While the former statement is definitely true since variable fonts do provide infinite typographical choices, the latter only holds under certain conditions.
Chrome DevTools: Treasure (Overview)
tl;dr
The Chrome DevTools are a neat collection of tools for the daily work as a web developer. If you're lucky, you'll maybe find some handy stuff in here.
Analysing
Breakpoints
- [Breakpoints on HTML Elements](https://makandracards.com/makandra/517982-chrome-devtools...
Chrome DevTools: DOM Breakpoints - Breakpoints on HTML Elements
tl;dr
In Chrome DevTools in the Elements tab or in Firefox in the Inspector tab you can right click on an element and choose Break on to debug changes related to this element.
Example
DOM Breakpoints can be quite useful to quickly find the JavaScript that is responsible for some (unexpected) behavior. You can use DOM Breakpoints for debugging subtree modifications, attribute modifications or node removal.
Here you can see a very simple example that shows what JavaScript lines are responsible for ...
Debug flaky tests with an Unpoly observeDelay
The problem
Unpoly's [up-observe], [up-autosubmit] and [up-validate] as well as their programmatic variants up.observe() and up.autosubmit() are a nightmare for integration tests.
Tests are usually much faster than the configured up.form.config.observeDelay. Therefore, it may happen that you already entered something into the next field before unpoly updates that field with a server response, discarding your changes.
The steps I wait for active ajax requests to complete (if configured) and capybara-lockstep can catch some ...
Git: Restore
tl;dr
git checkoutis the swiss army of git commands. If you prefer a semantically more meaningful command for restoring tasks, usegit restoreinstead.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...
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...
RubyMine: Find and Replace with Regex (Capture Groups and Backreferences)
tl;dr
In RubyMine you can use find and replace with capture groups
(.*?)and backreferences$1(if you have several groups:$[Capture-Group ID]).
Named captures(?<text>.*)are also supported.
Examples
Replace double quotes with single quotes
If you want to replace double quotes with single quotes, replacing every " with a ' is prone to errors. Regular expressions can help you out here.
- Open find and replace
- Activate the regex mode (click on the
.*icon next to the "find" field). - Fill in f...
SEO: The subtle differences of robots.txt disallow vs meta robots no-index
The robots.txt file and <meta name="robots"> HTML tag can be used to control the behavior of search engine crawlers. Both have different effects.
robots.txt
Marking a URL path as "disallowed" in robots.txt tells crawlers to not access that path.
robots.txt is not a guarantee for exclusion from search engine results.
A "disallowed" URL might be known from an external link, and can still be displayed for a matching search.
Example: even if/adminis disallowed in robots.txt, `/admin/som...
Ruby and Rails: Debugging a Memory Leak
A memory leak is an unintentional, uncontrolled, and unending increase in memory usage. No matter how small, eventually, a leak will cause your process to run out of memory and crash.
If you have learned about a memory leak, looking at the number of Ruby objects by type can help you track it down:
> pp ObjectSpace.count_objects
{:TOTAL=>77855,
:FREE=>4526,
:T_OBJECT=>373,
:T_CLASS=>708,
:T_MODULE=>44,
:T_FLOAT=>4,
:T_STRING=>65685,
:T_REGEXP=>137,
:T_ARRAY=>984,
:T_HASH=>87,
:T_STRUCT=>12,
:T_BIGNUM=>2,
:T_FILE=>3,
:T_D...
Rails: Custom validator for "only one of these" (XOR) presence validation
For Rails models where only one of multiple attributes may be filled out at the same time, there is no built-in validation.
I've seen different solutions in the wild, each with different downsides:
- Private method referenced via
validate: works, but is barely portable and clutters the model. - Multiple presence validations with "if other is blank" each: looks pretty, but is incorrect as it allows both values to be filled in; also the error messages for a blank record are misleading.
Here is a third option: Write a custom validator to ...
Yarn: Use yarn-deduplicate to cleanup your yarn.lock
Note
Use
yarn dedupein Yarn v2+: https://yarnpkg.com/cli/dedupe
This package only works with Yarn v1. Yarn v2 supports package deduplication natively!
A duplicate package is when two dependencies are resolved to a different version, even when a single version matches the range specified in the dependencies. See the Deduplication strategies section for a few examples.
Yarn is stupid, so it can happen that there are several version of the same package in your bundle, although one would fulf...
Rails: Fixing the memory leak / performance issues in prepend_view_path
Recently we detected a memory leak in one of our applications. Hunting it down, we found that the memory leak was located in Rails' #prepend_view_path. It occurs when the instance method prepend_view_path is called in each request, which is a common thing in a multi-tenant application.
On top of leaking memory, it also causes a performance hit, since templates rendered using the prepended view path will not be cached and compiled anew on each request.
This is not a new memory leak. It was [first reported in in 2014](https://github.com/...
A short overview of common design patterns implemented within Rails
The linked content includes a few design patterns implemented with Ruby on Rails.
What is the card indented to achieve?
- You can use the pattern names for code reviews, so all parties know with only a few words which change is requested. Example: "Please use a form object here"
- You can learn about new code patterns
- You should read the sections "Advantages of using design patterns" and "Disadvantages of using design patterns in a wrong way", since design patterns do not replace good code
Included Design Patterns: Service, Value objec...
makandra tech survey - results
These are the results of the "personal tech stack survey". I've included only the most popular mentions, maybe it can help you find one or two useful tools for your own usage.
Desktop environment
pie title Desktop environment
"Gnome" : 16
"i3": 2
"sway": 2
"awesome": 1
"bspwm": 1
"mate": 1
"xfce": 1
Gnome dominates (unsuprising, it's the Ubuntu default), but quite a few people use tiling window managers, most popular i3 and the mostly i3-compatible [sway](https://swaywm....
JavaScript: Testing whether the browser is online or offline
You can use the code below to check whether the browser can make connections to the current site:
await isOnline() // resolves to true or false
The code
The isOnline() function below checks if you can make real requests by re-fetching your site's favicon. If the favicon cannot be downloaded within 6 seconds, it considers your connection to be offline.
async function isOnline({ path, timeout } = {}) {
if (!navigator.onLine) return false
path ||= document.querySelect...
Josh McArthur: Fancy Postgres indexes with ActiveRecord
I recently wanted to add a model for address information but also wanted to add a unique index to those fields that is case-insensitive.
The model looked like this:
create_table :shop_locations do |t|
t.string :street
t.string :house_number
t.string :zip_code
t.string :city
t.belongs_to :shop
end
But how to solve the uniqueness problem?
Another day, another undocumented Rails feature!
This time, it’s that ActiveRecord::Base.connection.add_index supports an undocumented option to pass a string argument as the v...
How to debug file system access in a Rails application
It might sometimes be useful to check whether your Rails application accesses the file system unnecessarily, for example if your file system access is slow because it goes over the network.
The culprit might be a library like carrierwave that checks file existence or modification times, whereas your application could determine all this from your database.
Introducing strace
One option it to use strace for this, which logs all system calls performed by a process.
To do this, start your rails server using something like
DISA...
Capybara: Most okayest helper to download and inspect files
Testing file download links in an end-to-end test can be painful, especially with Selenium.
The attached download_helpers.rb provides a download_link method for your Capybara tests. It returns a hash describing the download's response:
details = download_link('Download report')
details[:disposition] # => 'attachment' or 'inline'
details[:filename] # => 'report.txt'
details[:text] # => file content as string
details[:content_type] # => 'text/plain'
Features
Compared to [other approaches](...