How to use ActiveSupport Concerns with dynamic relations
The usual way to build a relation in a ActiveSupport::Concern is this:
module MyModule
extend ActiveSupport::Concern
included do
scope :disabled, -> { where(disabled: true) }
end
end
However, if you have a association with a polymorphic model, where you have to select based on the kind of record, using included
like this will not produce the wanted results:
module MyModule
extend ActiveSupport::Concern
included do
has_many :tasks,
->...
RubyMine: How to exclude single files
In RubyMine folders can be excluded from search, navigation etc. by marking it as excluded. You might sometimes wish to exclude single files, too. An example could be .byebug_history
which is located in the project root directory.
Single files can be excluded by pattern in the Settings:
- In the Settings/Preferences dialog
Ctrl+Alt+S
, go to Project structure - In the Exclude files field, type the masks that define the names of files and folders to be exclu...
Carrierwave: Using a nested directory structure for file system performance
When storing files for lots of records in the server's file system, Carrierwave's default store_dir
approach may cause issues, because some directories will hold too many entries.
The default storage directory from the Carrierwave templates looks like so:
class ExampleUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
If you store files for 500k records, that store_dir
's parent directory will have 500k sub-directories which will cause some...
Debugging your Webpack build time with Speed Measure Plugin
If your Webpack build is slow, you can use the Speed Measure Plugin for Webpack to figure out where time is being spent.
Note that at time of writing, Webpack 5 seems unsupported. It works on Webpack 4, though.
Wire it into your application as described in the library's documentation:
- Hook into your environment file, e.g.
config/webpack/development.js
and instead of exporting your Webpackconfig
,...
Run code before or after an existing Rake task
Before
To run additional code before an existing Rake tasks you can add a dependency like this:
task :before_task do
# runs before :existing_task
end
Rake::Task[:existing_task].enhance [:before_task]
The new dependency will be called after all existing dependencies.
After
To run additional code after an existing Rake tasks, pass a block to enhance
:
Rake::Task[:existing_task].enhance do
# runs after :existing task
end
Webpacker: Loading code on demand
Sometimes you want to load code on demand. For instance, when a a large library is only used on a single screen, this library should only be loaded for that screen. It should not blow up the bundle size for all screens.
You can load code on demand by using import()
as a function (with parentheses) instead of using it as a keyword import
(without parentheses). The import()
function returns a promise with the exported variables:
let exports = await import('large-library')
console.log("A named export is ", exports.exportedName)
c...
When does Webpacker compile?
Webpack builds can take a long time, so we only want to compile when needed.
This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.
When you run a dev server
While development it is recommended to boot a webpack dev server using bin/webpack-dev-server
.
The dev server compiles once when booted. When you access your page on localhost
before the initial compilation, the page may load without assets.
The ...
Linux: Using grep with a regular expression
You can use three different versions of the regular expression syntax in grep
:
- basic:
-G
- extended:
-E
(POSIX) - perl:
-P
(PCRE)
Difference between basic and extended:
In basic regular expressions the meta-characters '?', '+', '{', '|', '(', and ')' loose their special meaning; instead use the backslashed versions '?', '+', '{', '|', '(', and ')'.
Difference between extended (POSIX) and perl (PCRE): E.g. \d
is not supported in POSIX.
This g...
How to iterate over an Enumerable, returning the first truthy result of a block ("map-find")
Ruby has Enumerable.find(&block)
, which returns the first item in the collection for which the block evaluates to true
.
first_post_with_image = posts.find do |post|
post.image
end
However, sometimes it's not the item you're interested in, but some value depening on it – e.g. the value the block evaluated to. You could first map the collection and then take the first truthy value, but this way you need to process the whole collection twice:
first_image_url = posts.map(&:image).find(&:present?).url
If the mapping ...
Limiting GitLab CI runner to specific branches or events
Use rules to include or exclude jobs in pipelines.
Rules are evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration. The job can also have certain attributes added to it.
rules replaces only/except and they can’t be used together in the same job. If you configure one job to use both keywords, the linter returns a key may not be used with rules error.
GitLab 12.3 introduced rules. You can use them in your .gitlab-ci.yml
in your proj...
Bundler: Packaging gems into the git repository (offline installation)
Installing gems on a server that has no access to the internet (especially rubygems.org
) requires to bundle the gems into the repository itself. This requires to adjust the bundle config in the repository.
- Execute the following commands to configure bundler:
bundle config set --local path vendor
bundle config set --local disable_shared_gems true
Note
For Bundler < 2 you have to omit the "set":
bundle config --local name value
.
See here: [https://bundler.io/v1.17/man/bundle-config.1.html](https://bundler.io/v1.17/man...
How to generate and test a htpasswd password hash
Generate a password
htpasswd -Bn firstname.lastname
This will ask you for a password and use bcrypt (-B
, more secure) and print the output to stdout (-n
).
Check if password matches the hash
You'll first have to write the password hash to a file:
echo firstname.lastname:$2y$05$4JXxd2GM/J2...9c3KJmFS > htpass_test
Check, if it is correct:
htpasswd -v htpass_test firstname.lastname
You probably should not use the -b
switch to read the password from the command line as the password will then be visible...
Emulating document.currentScript in old browsers
When you need the DOM node of a <script>
tag (e.g. to read extra attributes, or to modify the DOM near it), you can usually reference it via document.currentScript
.
However, document.currentScript
is unsupported in ancient browsers, like Internet Explorer 11 or wkhtmltopdf's Webkit engine.
If you are not running async scripts, you can easily polyfill it:
document.scripts[document.scripts.length - 1]
It works because document.scripts
grows with each <script>
tag that was evaluated.
That is also the reason why th...
Capistrano: Deployment issue undefined method `[]' for nil:NilClass
In newer passenger versions the output of passenger -v
has changed. capistrano-passenger
tries to parse the version and now causes the error undefined method '[]' for nil:NilClass
. To fix this you only need to upgrade the capistrano-passenger
gem.
Therefore run bundle update capistrano-passenger --conservative
.
The version change of passenger from 6.0.7
to 6.0.8
has triggered this problem. This is fixed in capistrano-passenger >= 0.2.1
.
How to explain SQL statements via ActiveRecord
ActiveRecord offers an explain
method similar to using EXPLAIN
SQL statements on the database.
However, this approach will explain all queries for the given scope which may include joins
or includes
.
Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:
User.where(id: 1).includes(:articles).explain
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
+----+-------------+-------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-----...
What does 100% mean in CSS?
The attached article examines what the percent unit (%
) is relative to in CSS
The article does a great job of visualizing the dependencies. The TLDR is:
Own property | % of |
---|---|
height |
parent height |
width |
parent width |
top |
parent height |
left |
parent width |
margin-top |
parent width |
margin-left |
parent width |
padding-top |
parent width |
padding-left |
parent width |
Converting ES6 to ES5 on the command line
I use the TypeScript compiler for this, since its output is more minimal than Babel's.
The following will transpile all src/*.js
files into a file build.js
:
npm install typescript
npx tsc src/*.js --target ES5 --allowJs --outFile build.js
The output will only transpile ES6 syntax. It will not include any polyfills for missing APIs.
RubyMine: How to restore the Back to last position shortcut on Ubuntu 20.04
I really love to use the shortcuts CTRL
+Alt
+ Arrow Left
and CTRL
+Alt
+ Arrow Right
to navigate through the code. It worked great on Ubuntu 18.04 and MATE but after migrating to my new notebook with GNOME and Ubuntu 20.04, I realized that the shortcuts didn't work anymore. Well, it worked via Navigate > Back
and also showed the shortcut, but my fingers weren't able to do this...
I cried a lot. (Why God? WHY?)
Then I found this [thread on StackOverflow](https://stackoverflow.com/questions/47808160/intellij-idea-ctrlaltleft-short...
Ruby: How to convert hex color codes to rgb or rgba
When you have a hex color code, you can easily convert it into its RGB values using plain Ruby.
>> "#ff8000".match(/^#(..)(..)(..)$/).captures.map(&:hex)
=> [255, 128, 0]
You can use that to implement a simple "hex to CSS rgba value with given opacity" method:
def hex_color_to_rgba(hex, opacity)
rgb = hex.match(/^#(..)(..)(..)$/).captures.map(&:hex)
"rgba(#{rgb.join(", ")}, #{opacity})"
end
>> hex_color_to_rgba("#ff8000", 0.5)
=> "rgba(255, 128, 0, 0.5)"
If you need to support RGBA hex color codes,...
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...