Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
JoshCheek / the_devils_typecasting.rb
Created September 10, 2021 05:19
The Devil's Typecasting in Ruby!
require 'fiddle'
public def to_ptr
Fiddle::Pointer.new Fiddle.dlwrap self
end
public def to!(klass)
to_ptr[8, 8] = klass.to_ptr.ref[0, 8]
end
@JoshCheek
JoshCheek / memoize_example.rb
Last active August 14, 2021 11:51
Memoizing a method with an optional default value without receiving splat args
module Memoize
NOT_SET = Module.new
private_constant :NOT_SET
def memoize(method_name)
meth = method method_name
case meth.parameters.map(&:first)
when [:opt]
define_method method_name do |arg=NOT_SET|
_memoizations.fetch arg do
@JoshCheek
JoshCheek / ruby2_keywords_flag.rb
Last active July 31, 2021 15:03
The flag that `ruby2_keywords` uses
# https://twitter.com/josh_cheek/status/1421462056994283521
require 'fiddle'
public def address() = Fiddle.dlwrap(self)
public def pointer() = Fiddle::Pointer.new(address)
public def toggle_keywords!() = (pointer[1] ^= 0b100000)
def m(a:) = a
h = {a: 1}
m *[h] rescue $! # => #<ArgumentError: wrong number of arguments (given 1, expected 0; required keyword: a)>
@JoshCheek
JoshCheek / ruby_2_and_3_keyword_args.rb
Created July 31, 2021 03:48
Ruby 2 & 3's keyword args and how `ruby2_keywords` works
# Helpers to make the code below easier to read
class Array
def keywords?() = Hash.ruby2_keywords_hash?(self[-1])
def to_keywords!() = (self[-1] = Hash.ruby2_keywords_hash(self[-1]))
end
# Code to facilitate the examples below
def record_args(*args) = args
def call_this(val:) = val
@JoshCheek
JoshCheek / postgresql_savepoints_will_recover_from_errors_inside_transactions.rb
Created July 22, 2021 18:55
Using PostgreSQL's savepoints to recover from errors while inside a transaction
# 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 July 22, 2021 06:31
Search Path Example (postgresql)
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 July 13, 2021 14:20
ActiveRecord query parameterization inconsistency
# 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 July 13, 2021 13:14
How to parameterize SQL queries in a migration in Rails.
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 July 3, 2021 19:14
Alternative version of type checking that doesn't use method_added
# 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 July 3, 2021 18:59
Using `method_added` to detect the next method
# 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)