Construct an array with _ index
Blocksyntax:
years = Array.new(11) { Time.now.year + _1 }Hier wird Array.new(11) verwendet, um ein Array mit 11 Elementen zu erstellen (einschließlich des aktuellen Jahres), und der Block { Time.now.year + _1 } berechnet das Jahr für jedes Element (beginnend mit dem aktuellen Jahr). _1 ist ein Platzhalter für den Index des Blocks (ab 0).
rspec --profile gives a performance overview
Using --profile in your rspec command line allows you to see the slowest 10 examples in your test suite, along with a speed benchmark.
For more, see:- https://rspec.info/features/3-13/rspec-core/configuration/profile/
Example:
$ bundle exec rspec ./path/to/my/test.rb:90
Top 10 slowest examples (54.21 seconds, 73.1% of total time):
# displays list of examples here with benchmark
Finished in 1 minute 7.22 seconds
Fake HTTP responses and response times
If you need an HTTP endpoint replying with a specific HTTP status code or taking a specific response time: try https://httpstat.us!
For example:
- return a 200 OK success status, taking 5 seconds: https://httpstat.us/200?sleep=5000
- return a 400 Bad Request: https://httpstat.us/400
yes and no are booleans when used as keys in YAML
Whilst fixing a strange bug, I learnt today that yes and no are actually boolean key values in yaml.
E.g. We take this line of ruby:
booking.feedback_done ? I18n.t("billing.billing_public_tours.yes") : I18n.t("billing.billing_public_tours.no"),calling #feedback_done should simply return a boolean value, so all looks okay right?
[2] pry(#<#<Class:0x0000000162290e60>>)> booking.feedback_done ? true : false
=> falseIf we take a look at our YAML:
billing_public_tours:
...
yes: "Ja"
no: "Nein"Our translations look correctly configured. So why do we get this?
[1] pry(#<#<Class:0x0000000162290e60>>)> booking.feedback_done ? I18n.t("billing.billing_public_tours.yes") : I18n.t("billing.billing_public_tours.no")
=> "Translation missing: de.billing.billing_public_tours.no"Because Booleans are formatted as English words in YAML
If we wrap them in quotes:
billing_public_tours:
...
"yes": "Ja"
"no": "Nein"Our code will now work:
[1] pry(#<#<Class:0x000000016dff30c0>>)> booking.feedback_done ? I18n.t("billing.billing_public_tours.yes") : I18n.t("billing.billing_public_tours.no")
=> "Nein"
git commits from then to now
To show all commit “children” from a specific commit to current master, use git log
like
git log --reverse --ancestry-path 894e8b4e93d8f3^..master
Method git history with `git log -L`
Today I found out that - via git log -L - it’s possible to list the history of changes to a specific method:
$ git log -L :initialize:app/lib/giant_money.rb -n5
commit e6ef7f8a3cf06af2ecbf8a528ad5cf312a8d03b1
Author: Alexander Presber <post@momolog.info>
Date: Sun Aug 13 20:05:59 2023 +0200
don't fail hard (yet) on GiantMoney[nil] [GOM-8932]
diff --git a/app/lib/giant_money.rb b/app/lib/giant_money.rb
--- a/app/lib/giant_money.rb
+++ b/app/lib/giant_money.rb
@@ -16,12 +16,16 @@
def initialize value, allow_nil: false
- raise "GiantMoney.new: value cannot be nil." unless value || allow_nil
+
+ unless value || allow_nil
+ # raise "GiantMoney.new: value cannot be nil." # don't fail hard (yet) on GiantMoney[nil]
+ Rollbar.error("GiantMoney.new: value cannot be nil in #{caller[2]}.", stack: caller)
+ end
@amount = case value
when nil then nil
when Money then value
when Integer then Money.new(value)
when Float then Money.new((value * 100.0))
else raise 'GiantMoney.new: value needs to be an Integer, Float or Money object.'
end
end
commit f55678a8c33029b1e998e1e0b6d536afd2f77107
Author: Lion Vollnhals <lion@giantmonkey.de>
Date: Fri Jun 9 12:58:05 2023 +0000
giant_monkey: multiple float by float
diff --git a/app/lib/giant_money.rb b/app/lib/giant_money.rb
--- a/app/lib/giant_money.rb
+++ b/app/lib/giant_money.rb
@@ -16,12 +16,12 @@
def initialize value, allow_nil: false
...Noice.
Copy-paste friendly executable comments in Ruby
Imagine this comment on top of a ruby file:
### usage:
#### reset and seed database
# rake db:reset
#### get korona base data
# rails runner 'Korona.synchronize_all!'
#### create valid day tickets in local development
# rails runner rails-runner/create_valid_ticket_for_shop_tests.rbIt is supposed to document the usage and gives executable example lines. However to use them verbatim you have to copy-paste them line by line, removing the leading #.
There is a better alternative using the mostly frowned upon=begin / =end comment style:
=begin usage:
rake db:reset # reset and seed database
rails runner 'Korona.synchronize_all!' # get korona base data
rails runner rails-runner/create_valid_ticket_for_shop_tests.rb # create valid day tickets in local development
=endNow it is possible to copy-paste the whole block into a shell to execute.
Ours and theirs in git rebase
When resolving a conflict while doing a git rebase, --ours does not refer to the branch we are currently on (the one being rebased) but the base branch, e.g. main.
While arguably being pretty confusing, this actually has a good reason.
A nice cheat sheet is here.
Hyphens and underscores in mysql.cnf
According to this bug_and - may both be used in mysql / mariadb configuration options inside the mysql.cnf file.
E.g.
[mariadb]
log-bin # enable binary loggingand
[mariadb]
log_bin # enable binary loggingare both ok!
For googling and searching inside pages the _ variant usually works better.
Capybara content matchers cheat sheet
There’s a cheat sheet I use to determine the capybara content matcher to use for a specific purpose:
Wait for some text to eventually be there:
expect(page).to have_content('some text')Succeeds as soon as the text is there and can be very fast.
Wait for some text to be - and stay - there:
expect(page).not_to have_no_content('some text')Succeeds if the text stays there for the whole default_max_wait_time and is therefore always slow. But sometimes needed.
Wait for some text to eventually disappear:
expect(page).to have_no_content('some text')Succeeds as soon as this text is not there and can be very fast.
Wait for some text to be - and stay - absent:
expect(page).not_to have_content('some text')Succeeds if the text stays absent for the whole default_max_wait_time and is therefore always slow. But sometimes needed.
TIL to log-into til.giantmonkey.de
I needed some time because it’s not obvious, but now it’s easy. Just open https://til.giantmonkey.de/admin and sign in with your giant monkey google account …
make firefox to accept puma-dev cert permanently
every time, firefox is restarted, and i’m opening https://gomus.test again, the cert has to be accepted manually again.
- use
open ~/Library/Application\ Support/io.puma.dev/in terminal to show your local puma-dev certs folder - enter
about:preferences#privacyinto firefox url-bar - all the way at the bottom you’ll find Certificates
- click on View Certificates
- in the last Authorities tab, you can import the Puma-dev certificate you’ve revealed in first step
- you only need to accept this for websites …
from now on, firefox will without any disturbance open local https:// puma-dev websites.
capybara: save page to disk
Today i learned that capybara’s save_and_open_page statement is a gem to debug the current page capybara wants to test.
Sandboxed rails console
If you want to do some changes to your models in the console but want them to be rolled back after your session, just use
rails console --sandboxStraight from the docs.
It’s not a good idea to use this in production, though.
Ripgrep: searching with negative lookahead
Using ripgrep we can search using PCREs. First we need to enable pcre expressions in ~/.ripgreprc:
--pcre2Then we can search for all occurences of mywordnot followed by _:
> rg 'myword(?!_)'
TIL how to check the progress of a recursive grep
If you want to check the progress of a recursive grep, going trough lots of files, just sudo ls -lah /proc/[GREP PID]/fd. You’ll see which files grep is accessing at the moment, which will give you an idea how far it is in the search.
Ansible: decrypt single vault value in the shell
$ ansible localhost -m debug -a 'var=my_password'
localhost | SUCCESS => {
"my_password": "not secret anymore"
}
Delete duplicates with PostgreSQL using USING
Consise way to delete duplicates (depending on a condition, e.g. col1 and col2 being equal) while keeping the row with the highest id:
DELETE FROM
my_table delete
USING my_table check
WHERE
delete.id < check.id
AND delete.col1 = check.col1
AND delete.col2 = check.col2
You can jump to slash in zsh
After changing from bash to zsh I found it quite annoying that ⌥ + ← was always jumping to the closest white character, instead to space or slash (or some other special characters considered to be word-separators).
Fortunately it’s possible to change this behaviour by editing the WORDCHARS env variable.
Source: https://github.com/ohmyzsh/ohmyzsh/issues/5108#issuecomment-233480020
Rebase without having anything pushed yet
Prototyping should also be cleaning up commits before first push. How to do that?
Well, git rebase --interactive --root masterdoes the trick.
Thanks to https://troglobit.com/howto/rebase-without-an-origin/
Tom's Obvious, Minimal Language isn't so obvious
TIL that order really matters when it comes to Tom’s Obvious, Minimal Language aka TOML.
https://gitlab.giantmonkey.de/docker/gitlab-runner/-/merge_requests/20
Breaking the runner
Today I learned that our GitLab runner deploys itself. Which means that if you push a change which breaks it, later when you’ll try to fix it, it won’t be there to deploy the fix.
Cloud Tasks need App Engine to be enabled
Today I learned that even though cloud tasks are a separate product now they still need your App Engine project to be enabled. Otherwise, all tasks will just hang and any attempt of forcing them to execute will result in a 500 error.
Using ngrok with puma-dev
If you have a local Rails/Rack server running using puma-dev, e.g. http://gomus.test and you want to use ngrok for accessing this server from remote, you can pass a --host-header=gomus.test to ngrok.
ngrok http --host-header=gomus.test localhost:80Happy hacking!
Fixing file permissions in git repository
If you mess up your file permissions in a git repository you can easily reset them back to how they were with this simple command:
git diff -p -R --no-color \
| grep -E "^(diff|(old|new) mode)" --color=never \
| git applyFrom this gist: https://gist.github.com/jtdp/5443498
This is not a usual problem, and can if on the off chance it does occure you can normally solve it by a simple checkout or hard reset, but in my case I also had uncommited changes to files in the repository alongside the permission changes which I really wanted/needed to keep!
Sidenote
If you are wondering how you could end up in this situation in the first place… well, my story is I backed up a complete copy of my projects folder onto a HD when I installed my laptop from fresh. This was the easiest way for me to ensure that I would have all of my local changes in projects just in case I had forgotten to commit and push somewhere! After copying them back every repo was full of file permission changes.
Javascript Array.prototype.sort() ...
… by default converts the array elements into strings and sorts them by their UTF-8 Codepoints 🤪!
[-7, 2, 10, -1].sort()
[-1, -7, 10, 2]You can pass a function to sort to override the behavior:
[-7, 2, 10, -1].sort(function(a,b){ return a - b })
[-7, -1, 2, 10]Phew.
running sidekiq job in console
working with clients database locally has to be done without having sidekiq running to prevent side-effects like causing relay-interactins, mail-sends and others. but. sometimes, to debug burried mantraps you have to use the local connsole and you like to execute a task, which is usually performed by sidekiq. there is a simple way to run those tasks locally.
asuming that you have one item in your queue to execute, you can easy run:
job = Sidekiq::Queue.new("low").first
job.klass.constantize.new.perform(*job.args)if you have to find something by the id shown in backend, you can utilize the Sidekiq API for distinct access.
"Fixing" frontend form validations
Some form inputs apply pattern checks (e.g. on the telephone number).
An example: <input type="tel" name="field_mobil" class="phone form-control col-md-3" id="input-handy" value="" required="" size="20" pattern="[0-9]+">.
This specific one made the form not accept my telephone number even though it was correct.
Removing the pattern attribute using the WebInspector made the “validation” go away.
This is just to be expected, but still something that feels weird.
DGN provides free S/MIME certificates
The “Deutsches Gesundheitsnetz” offers free S/MIME certicate creation. These certificates work with Apple Mail (and presumably with Google Mail, but the steps for installing are not completely clear to me) and are valid for one year.
Get the database URL of a Gigalixir app via CLI
Install jq if you haven’t already.
Then
gigalixir pg | jq ".[0].url"
Gigalixir is a Heroku alternative for Elixir
Heroku works as a platform for deploying Elixir apps, but has some serious limitations.
Gigalixir is an interesting alternative that was tailored to provide the full Elixir experience in a very Heroku-like fashion including
- a powerful CLI
- configuration via env vars and
- deployments via
git push.
You can see it working right here!