Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
JoshCheek / postgresql_savepoints_will_recover_from_errors_inside_transactions.rb
Created Jul 22, 2021
Using PostgreSQL's savepoints to recover from errors while inside a transaction
View postgresql_savepoints_will_recover_from_errors_inside_transactions.rb
# these are Ruby 3's endless methods
require 'pg'
db = PG.connect
def db.exec_params(...) = super.map { |h| h.transform_keys &:intern }
def db.exec(...) = super.map { |h| h.transform_keys &:intern }
# transactions methods
def db.begin() = exec('begin')
def db.save(name) = exec("savepoint #{name}")
def db.rollback_to(name) = exec("rollback to #{name}")
@JoshCheek
JoshCheek / pg_search_path_example.rb
Last active Jul 22, 2021
Search Path Example (postgresql)
View pg_search_path_example.rb
require 'pg'
$db = PG.connect # to default db
# override the `exec` method so that query results get displayed
def $db.exec(*, **)
super.map { |r| r.transform_keys &:intern }
end
# A schema with a table in it
def make_schema
@JoshCheek
JoshCheek / active_record_query_parameterization_inconsistency.rb
Last active Jul 13, 2021
ActiveRecord query parameterization inconsistency
View active_record_query_parameterization_inconsistency.rb
# DB setup
require 'active_record'
ActiveRecord::Base.establish_connection adapter: 'postgresql', database: 'testdb'
ActiveRecord::VERSION::STRING # => "6.1.3.2"
# Helper method so errors don't kill the program
def show
yield
rescue StandardError => err
(err.cause||err).message.lines.first.strip
@JoshCheek
JoshCheek / rails_migration_parameterization_example.rb
Created Jul 13, 2021
How to parameterize SQL queries in a migration in Rails.
View rails_migration_parameterization_example.rb
class Omghi < ActiveRecord::Migration[6.1]
def up
# Some value we want to use in our query, that we don't want to interpolate.
# The answers on Stack Overflow say to escape this param and then interpolate
# it into the query, but when I went to OWASP training, they were pretty
# emphatic that sanitization is inferior to parameterization. I don't 100%
# know why (it was a giant auditorium, I didn't raise my hand and ask)
param = 'hello world'
# By using `exec_query` instead of `execute`, we can pass params.
@JoshCheek
JoshCheek / type_checking_without_method_added.rb
Created Jul 3, 2021
Alternative version of type checking that doesn't use method_added
View type_checking_without_method_added.rb
# convo: https://twitter.com/dorianmariefr/status/1411306589739433984
# alternative to this: https://gist.github.com/JoshCheek/df6154555387f966ef1808262e38f72e
# We'll ignore everything except required args, to keep it simpler
private def with_types(*ordtypes, name)
# I guess this works for main, and singleton methods on `self`, but not singleton methods
owner = is_a?(Module) ? self : method(name).owner
meth = owner.instance_method(name)
params = meth.parameters
@JoshCheek
JoshCheek / type_check_with_method_added.rb
Created Jul 3, 2021
Using `method_added` to detect the next method
View type_check_with_method_added.rb
# https://twitter.com/dorianmariefr/status/1411306589739433984
# We'll ignore everything except required args, to keep it simpler
private def with_types(*ordtypes)
mod = is_a?(Module) ? self : Object # to handle edge-case of `main`
mod.module_eval { @next_types = ordtypes }
end
class Module
def method_added(name)
@JoshCheek
JoshCheek / pipeline.rb
Created Jun 29, 2021
Ruby pipeline, based on JS example
View pipeline.rb
# https://babeljs.io/blog/2018/07/19/whats-happening-with-the-pipeline-proposal
module Pipeable
def |(fn)
fn.to_proc.call self
end
refine(Enumerable) { include Pipeable }
refine(Proc) { include Pipeable }
refine(Array) { include Pipeable }
@JoshCheek
JoshCheek / example.rb
Created Jun 28, 2021
Ruby's three dot arguments misreport their parameter types
View example.rb
p RUBY_VERSION: RUBY_VERSION
def ab(a, b:)
[a, {b: b}]
end
puts "Three dots:"
def dots(...) ab(...) end
pp real_sig: method(:ab).parameters,
wrapper_sig: method(:dots).parameters,
@JoshCheek
JoshCheek / f.cpp
Last active Jun 26, 2021
Pretty sure C++ refs are just obfuscating syntax around pointers
View f.cpp
// code for the screenshot in this tweet https://twitter.com/josh_cheek/status/1408853467150663680
#include "stdio.h"
void inc1(int& n) { ++ n; }
void inc2(int* n) { ++*n; }
int main(int argc, char** argv) {
int a = 0, b=0;
printf("a=%d, b=%d\n", a, b);
inc1(a); inc2(&b);
@JoshCheek
JoshCheek / module2_examp.rb
Created Jun 24, 2021
Example of how modules could keep track of what code to run on instances and what to run on classes and then generally work correctly whether extended or included
View module2_examp.rb
# An example to help me explain my thoughts in this tittwer convo:
# https://twitter.com/dorianmariefr/status/1407972746093641732
#
# Note that I ran this code on MRI 3.0.1, I assume it works on other versions too, but I did not try it.
# -----------------------------------------------------------------
# For simplicity, we'll only deal with keyword args in this example,
# I initially wrote it to deal with ordinals and blocks, but that got pointlessly dense