There is no such thing as a Ruby Ninja
Janteloven, fam.

“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it Currently working for GenieBelt who are based in Copenhagen, Denmark ...”
Janteloven, fam.

What with everything going on recently, and don’t get me wrong they are exciting things, I didn’t get round to buying a COPENHELL ticket and it will the first year in 8 that I won’t be going. No really. I’ll write code for a ticket. And. Yes Pustulant Flesh ate my dog’s homework

As per usual native extensions don’t always install 1st time. Damn…
bundle add ruby-libgd
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Fetching gem metadata from https://rubygems.org/.........
Fetching ruby-libgd 0.1.9
Installing ruby-libgd 0.1.9 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
The error is right there.
gem install ruby-libgd
Building native extensions. This could take a while...
ERROR: Error installing ruby-libgd:
ERROR: Failed to build gem native extension.
current directory: /Users/rl/.asdf/installs/ruby/3.4.6/lib/ruby/gems/3.4.0/gems/ruby-libgd-0.1.9/ext/gd
/Users/rl/.asdf/installs/ruby/3.4.6/bin/ruby extconf.rb
checking for -lgd... no
libgd not found
To see why this extension failed to compile, please check the mkmf.log which can be found here:
/Users/rl/.asdf/installs/ruby/3.4.6/lib/ruby/gems/3.4.0/extensions/arm64-darwin-24/3.4.0/ruby-libgd-0.1.9/mkmf.log
extconf failed, exit code 1
Gem files will remain installed in /Users/rl/.asdf/installs/ruby/3.4.6/lib/ruby/gems/3.4.0/gems/ruby-libgd-0.1.9 for inspection.
Looks like libgd is already installed.
brew install libgd
==> Auto-updating Homebrew...
Adjust how often this is run with `$HOMEBREW_AUTO_UPDATE_SECS` or disable with
`$HOMEBREW_NO_AUTO_UPDATE=1`. Hide these hints with `$HOMEBREW_NO_ENV_HINTS=1` (see `man brew`).
==> Downloading https://ghcr.io/v2/homebrew/core/portable-ruby/blobs/sha256:1c98fa49eacc935640a6f8e10a2bf33f14cfc276804b71ddb658ea45ba99d167
##################################################################################################################################################################################### 100.0%
==> Pouring portable-ruby-3.4.8.arm64_big_sur.bottle.tar.gz
==> Auto-updated Homebrew!
Updated 4 taps (heroku/brew, mongodb/brew, homebrew/core and homebrew/cask).
---8<----
You have 125 outdated formulae and 2 outdated casks installed.
Warning: gd 2.3.3_6 is already installed and up-to-date.
To reinstall 2.3.3_6, run:
brew reinstall gd
So I need to include the path the native libraries when installing.
gem install ruby-libgd -- --with-gd-include=/opt/homebrew/include --with-gd-lib=/opt/homebrew/lib
rl@loathsome fossa % bundle install
Bundle complete! 24 Gemfile dependencies, 125 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
1 installed gem you directly depend on is looking for funding.
Run `bundle fund` for details
Old blog posts I never published, except I have now #12
Say we wanted to schedule a job but wanted to limit duplicate jobs running within a specific time period. We could set a time for a job to run and ignore duplicate requests in our queue. It appears Ruby’s Time object makes this simple for us. We can round up (or floor) to the nearest, time interval. Nice.
2.2.2 :012 > Time.now.floor(15.minutes)
=> "2016-02-29T17:15:00.000+00:00"
2.2.2 :013 > Time.now.round(15.minutes)
=> "2016-02-29T17:30:00.000+00:00"
Ok, I’m doing it. Ruby 4.0.0 come at me brah
rl@macbookair personal % asdf plugin update ruby
Location of ruby plugin: /Users/rl/.asdf/plugins/ruby
Updating ruby to master
From https://github.com/asdf-vm/asdf-ruby
1ce84e2..8f28d3a master -> master
1ce84e2..8f28d3a master -> origin/master
Already on 'master'
Your branch is up to date with 'origin/master'.
rl@macbookair personal % asdf install ruby 4.0.0-preview2
ruby-build: using openssl@3 from homebrew
==> Downloading ruby-4.0.0-preview2.tar.gz...
-> curl -q -fL -o ruby-4.0.0-preview2.tar.gz https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0-preview2.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 22.3M 100 22.3M 0 0 17.5M 0 0:00:01 0:00:01 --:--:-- 17.5M
==> Installing ruby-4.0.0-preview2...
ruby-build: using libyaml from homebrew
ruby-build: using gmp from homebrew
-> ./configure "--prefix=$HOME/.asdf/installs/ruby/4.0.0-preview2" --with-openssl-dir=/opt/homebrew/opt/openssl@3 --enable-shared --with-libyaml-dir=/opt/homebrew/opt/libyaml --with-gmp-dir=/opt/homebrew/opt/gmp --with-ext=openssl,psych,+ --enable-yjit
It’s not uncommon for Rails specs to kill our database in development. It appears that if a browser spec doesn’t close cleanly you can end up with processes just hanging and so the next spec run will just wait forever.
Here’s the process list. It’s sleeping on the job.
MariaDB [(none)]> SHOW PROCESSLIST;
+-----+-------+-----------------+------------+---------+------+----------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+-----+-------+-----------------+------------+---------+------+----------+------------------+----------+
| 357 | painy | localhost:52732 | painy_test | Sleep | 563 | | NULL | 0.000 |
| 358 | painy | localhost:52733 | NULL | Sleep | 565 | | NULL | 0.000 |
| 363 | painy | localhost:53036 | painy_test | Sleep | 384 | | NULL | 0.000 |
| 364 | painy | localhost:53037 | NULL | Sleep | 436 | | NULL | 0.000 |
| 381 | robl | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST | 0.000 |
+-----+-------+-----------------+------------+---------+------+----------+------------------+----------+
5 rows in set (0.000 sec)sql
Probably just best to kill these processes and get on with our lives.
MariaDB [(none)]> KILL 357;
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> KILL 363;
Query OK, 0 rows affected (0.000 sec)sql
Old blog posts I never published, except I have now #11
Rails.configuration.exceptions_app.call({'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/404', 'rack.input' => ''})[2].body
Old blog posts I never published, except I have now #10
O$$$$$$ZZO$NNDMMMMNDDDDMNNNNDNZZ$$7II$OOZOD88DO8NO8I?DD?$$$$7777III??????+++77I?
8ZZZZZZZZD$NDNMMMMDDNDMMMMND8OZ$$$$$ZO8D8OO8NNNNNDD$ID8?$$$$7777IIIDNDN$???7$7I?
DD8888OOODDMNNMMMNDDNDMMNNDD88OZ888DNDN88O8NNNNNNNNDZ8D7$$$7$Z8DDDDMMNN$II77II??
DOOOOOODDNDNDDMMMNNNDMNND8OOZ$O88NMMMMN8OZ8DDNMMMMMMNDD$Z$$DD88D88NMMNN7I??$$7?I
NNNNNMNNNNNN8OMMNDONNMMD8O7$ZZZ88MMMMND8OOO88DNMMMMMMMNZZ$$8DDD8NNMMMMNZI7?I7II?
8ODDNDOZZZZZZZMMNDNNMN8OZ$7ZZ$ZDDMNN8$7I$$$OO8DNMMMMMMM8OZZDDDDDDDMNNNNZ7?$IO7?I
ZOZONDD$NDDD8DMMNNNMNM88$I7$$ONNNDO$???I7$$ZOO8DDNMNMMMMDZ$8DDDDMDNNNNMOII7ZZ$7$
O8ZONN8$DODD8ND8O$7$7$77I?77Z8D8ZI??++?II$$ZOO888DNMMMMMM8Z8DDDDMMMNMMM8Z777Z7?$
OZZONNZZN8D8$8DMMMMNNZZ?III$ONNO+~:~=+??I$$ZZO8888DNMMMMMMZDDNNDMNMMNMMO77$??I87
DNNN8DDD88DDDDONNNND8Z=??7$$8ND$~::~=+?I7$$$ZZO88DDDNMMMMMMDDNDNMMMMMMMO$Z77III$
D8$DDD88DNNDDDZNNN8DZ+~+I7ZZNDZ?:,,:~+?I$$$7$ZO888DDNMMMMMMNDDNNMMMMMMMDO7IIII?I
ZOZDDZDDO8OOOO$NNNDZ7~=IIZ88D8+~,,,:~=+?7ZZ7$ZO8888DNMMMMMMMNNDNNMMMMMMDIIII????
$$ZD888D$OZZDD8NNN87=~+7IODNNO=,,,~=??=I$ZZ7$ZO88DDDNNMMMMMMNMMMMMMMMMMDII7?????
O88888OO8DDD8ZZMNO7~=+I$II8MDO:,=I7$$ZZZOOOOOO8NNMNMNMMMMMMMMMMMMMMMMMMNII??????
$8888ZO8OZ$7D88MM7===II$I$8MN8=+$$ZO8D8OZ$ZO8DDND8O88DMMMMMMMMMMMMMMMMMM7I????I?
87O888D$$$DDDZ$M8++~+I$$$78ND8+=7$DNZ8OZI~I8DDDONMDNNDNMMMMMMNMMMMMMMMMM??++++++
8+=7$ZZZZ$$$$77$?=~==IZ$8ZDMDOI?=+7OO8Z?~,+ZNDND8DDDDDDMMMMMMNNMMMMMMMDNII??????
7=+..+??????IIII====+?Z$88NNDZ+~,:~?I7:,,.~$DDDDD888DDDMMMMMMMNMMMMMMMMMIII?????
I77I7Z88DDDDDD8I=:=~7O$8ONMM8+:,,:=?+,,...,?8NNDDD88D8DMMMMMMMNMMMMMMMMMIIII????
NNNNNMMMMM8NNZZ7++I+?O$ZDDMM8:,,,~==~=:,...+$OD888888DDMMMMMMMMNMMMMMMMMIIIIII??
8DMNMIDMN8NM$Z8?=?==IOZ$ONDMN,...,:~===,.,:?$Z87NND88DDMMMMMMMMNMMMMMMMMIII?I???
8888DNMMMMMDOO7?=?+I7OD7Z88NN. ...,:~==,=Z$77DDD88888DDMMMMMMMN8ODNMMMMMI???????
O8O888888D8DIII?++?7$ZDI$Z8NN. ....,:~:::~+7.~+7ZOONDDNMMMMMMMND$DDN87IIIIII????
OOO88888D8DOZ$$7I=+?7$OIZZDON....,.,,~=+?77.:?7ZZO8MNNMMMMMMMMMNNNMNNZDNDMMMMMNN
OOOOOO888DDONZZI$~++IZZZZ$88N:$7+:.:=?I77$.:?$O8DZO8DDMMMMMMMMMNNDNDNNNMMMMMMMMM
O88888OZZ88DD7ZI$?==+$7Z$ZZ$OM$$..~:I7$O8 .+7$I~+88888MMMMMMMMMMN8DDNMMMMDNNNMMM
MMNMMMNDD888O$I+I=:+=7OZZZZZ7DM8Z..=$:===..:?~.:?Z88NODDDMMMMMMMND888DMNMNDMMMMM
NMNNDD8DD8NO$ZI??:+?I$$OZZ8OOZNMD,. .7D$...:~,,+?$I?Z888ONMMMMMMMDD8DOOZ$NNDNMMM
$DOZD$DZDDO$7$I=:I77O8Z88888OONMMN.........,:,=++=~=?Z8D8MMMMMMMMNDD88OOZZZNMDNM
8ZO88D8N88O77Z::+7ODDOO8$ZDD8DNMMND. ......,,~===++=?7$$8DNMMMMMMD8888OOOZZZZDND
O88DMONONO7.~=~I==78ND8Z$Z8O8DNMMMN,.. . .:~+==?+??+=?$88MMMMMMNOOOZZOOOZZZZ8N
D$8DZNONZ.....77~+?78DD8$$ZOO8NMMMNN. .,:+==??I??=+I7ZOMMMMMNN8ZZZZ$$ZZZ$ZZZ
Z888DDZ.....=O=$I??IZDDDZ$8$8ONMMMMN... ..,:===+I?++??7$ZNMMMMNNDOZZ$$$$Z$ZZ$Z$
M8D$OI:==?I?+I7:7?IIIDD8DOO$ZDMMMMNN8.. ..~=++???+?I$$$ZOMMMMNNDOZZ$$$$Z$$$$$Z
DD$+=~.......::~:?77$8ZDNDD7ZODMMMNND. ..~=+++??++I7$$$ZMMMMNMN88Z$$7$7$$Z$7$Z
MZ+?+... .....~::.7$$O$8NMNZOZNMMMMD8~ ...:~=+??++?I7$$$ZDNMMMMNNDOZ$$777$$$777$
7=$O:..........~::.7ZOD$DNMND8DNMMMN8?....~=+???+?II77$$8NMMMMMNNDO$$7777$7777$$
~78O:...........=~:,7O8ZZNNNMDDNMMMN7....:~=+?++?777I7$O8MMMMMMMNNO$$777I$7I77$$
?DDI....~....~...+=~?ZO8$ZNNNMNNNMMO:...,=+++++I77777$ZO8MMMNNMMMNO$Z$777$I7777$
NNOI.....?.....=,,?+:IODZ$DD8MMNNMN+....:==+++I7777$$ZOZOMMMMMNMMNOZZ77$7III77I7
MNNO.....,....,.,=,I?+OZOOO888MMMN?....,~=+==I7777$Z$ZZZODNMMMMNMDD$Z$$Z77$77I77
MNN7....... ..,:~+==7?ZZDZONDDMMN7. ..,:==+??I7$7$ZO$ZZZONMMMMNNMNNZZZZ$7$777777
MM8,...........,,=+I77I$8O8NDDNMZ, ....~=++?777$$ZZ$$ZZDNNMMNNNNMMNZOZO$$$7777II
O8Z..............::=I$Z$Z8DNDDNN=.....:=+=~=7$$ZZ$$$ODZOD8MMNNNNMMMOZOZ$Z$$777I7
8ND...........::::::~=I$OONDDNDI. ...,~====+I$OOOZZ$Z8OZ8NMDNNMNNNNDO8OOZ$$7777I
NM8.. .......,~+===~~+$8NNNN8=....,~==+++?7ZOZZ$ZNOZZDONMMNNNNNDNNO8D8O$$$777I
DDD...........,..:=??+==+78NNN,....,:~===+?I$ZOZOZ$ZOZZ88DNMMNMMMNMOODDZ$OZ$$777
M88..........,:~:,,~?I??I?ZNN=. ..,:~=+=++I7ZOZZZZZZZZZZ8DNMMNNMMMDOO8$Z$8OZZ$77
MN8,..........,::~:,:+77I7ZD$, ...:~~=+++I7$Z8OZZZDOOZOZ88DNMMDMMNOOO8I777OOOZ$7
?NM8............,~=~~~+?77$O=. ..,~~==+??7$ZON8OOOONZZZOO8DNNMNMMNOO8DN8$NOMNOO$
MMMD.. ... .....,~===,,I$$I. ...:~=+++?I$$Z88DOOONMDDOON8DNNMNDMM888MMMZ88DMMMO
Old blog posts I never published, except I have now #9
I, [2015-01-22T07:15:59.225481 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.0ms)
I, [2015-01-22T07:15:59.225700 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.0ms)
I, [2015-01-22T07:15:59.225951 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.1ms)
I, [2015-01-22T07:16:00.561068 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (1307.7ms)
I, [2015-01-22T07:16:00.561527 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.1ms)
I, [2015-01-22T07:16:00.561772 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.1ms)
I, [2015-01-22T07:16:00.561993 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.1ms)
I, [2015-01-22T07:16:00.562210 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.0ms)
I, [2015-01-22T07:16:00.562425 #30041] INFO -- : Rendered api/characters/_character.json.jbuilder (0.1ms)
After realising that Bot traffic originating from China takes up significantly more hits to a store than normal traffic, we’re taken steps to try and block traffic to get analytics back in good order. Here are the CloudFlare rules we’ve gone with.
Blocks all traffic that Cloudflare sees as coming from China according to GeoIP.
(ip.geoip.country in {"CN" "RU" "KP" "SY"})
AS 4134 is the “ChinaNet Backbone” (China Telecom).
ip.src.asnum in {4134}
These are several ASNs owned by China Unicom. For example, AS 4837 is a well-known Unicom backbone. Cybercrime Information Center. AS 133118 and other ASNs (136958, 134543, 135061) are also associated with Unicom.
ip.src.asnum in {4837, 133118, 134543, 135061, 136958}
AS 9808 is commonly associated with China Mobile.
ip.src.asnum in {9808}
Uses Cloudflare’s threat scoring + bot detection to challenge likely bot traffic. Good for reducing automated “dead” sessions.
cf.threat_score > 20 and cf.client.bot
Fingers crossed this give us some respite.
