Skip to content

Instantly share code, notes, and snippets.

View kaspth's full-sized avatar

Kasper Timm Hansen kaspth

View GitHub Profile
@kaspth
kaspth / tapper.rb
Created March 18, 2024 13:52
For multiple chains of mutating methods, most likely on Enumerables.
class Tapper < BasicObject
def initialize(object) = @object = object
def method_missing(meth)
@object.tap(&meth)
self
end
end
class Object
# Spotify Mix Playlists: Assuming we have a history of played songs for a user,
# we have song recommendations via nearest neighbor search,
# and we have categorizations (genre, mood, era, instrumental/vocal, cultural/regional, theme),
# let system admins create mix templates based on music categorizations
# and then generate refreshable custom playlists for each user.
class User
has_many :playlists
has_one :history
end
# Here's the problem statement we worked on:
# 1. Spam post detection: Run a forum post through a series of configurable checks to give it a spam score,
# and flag the post when it crosses the threshold, with details on what led to the score.
# We had a Gemfile with `gem "rails"` and `gem "sqlite3"` in it, but that was it.
require "bundler/setup"
require "active_record"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
@kaspth
kaspth / stowaway.rb
Last active January 19, 2024 19:40
A Rails modeling implementation of https://brandur.org/soft-deletion
create_table :stowaway_records do |t|
t.string :record_type, null: false
t.jsonb :record_attributes, null: false, default: {}
t.timestamps
t.index :record_type
end
class Stowaway::Record < ActiveRecord::Base
def self.preserve(record)
create! record_type: record.class, record_attributes: record.attributes
@kaspth
kaspth / db-seeds-accounts-kaspers_donuts.rb
Last active November 1, 2023 02:58
A showcase of oaken, using data from its test suite. Early Access at: https://kaspthrb.gumroad.com/l/open-source-retreat-summer-2023
donuts = accounts.create :kaspers_donuts, name: "Kasper's Donuts"
kasper = users.create :kasper, name: "Kasper", accounts: [donuts]
coworker = users.create :coworker, name: "Coworker", accounts: [donuts]
menu = menus.create account: donuts
plain_donut = menu_items.create menu: menu, name: "Plain", price_cents: 10_00
sprinkled_donut = menu_items.create menu: menu, name: "Sprinkled", price_cents: 10_10
supporter = users.create name: "Super Supporter"

Here's the second weekly recap!

In last weeks recap, I shared where we were at in code and it looked like this:

# test_helper.rb
Oaken::Data.load_from "test/seeds"

# test/seeds/users.rb
User = Struct.new(:name, keyword_init: true)
@kaspth
kaspth / form_builder.rb
Created June 15, 2023 16:53
Trying to play around ideas with different FormBuilders for Rails.
class FormBuilder
def text_field(method, **options)
tag.input type: :text, **options_for(__method__, method, **options)
end
def options_for(type, method, index: @index, namespace: @options[:namespace], multiple: false, **options)
Options.new(self, type, method, index:, namespace:, multiple:, **options)
end
class Options
@kaspth
kaspth / themed_form_with.rb
Last active June 14, 2023 14:21
A pitch to have the ability to go between several form builders in a form, focused on Bullet Train's themed field partials.
# Provide a BulletTrain::Theme::FormBuilder, with extensions to
# go between Rails standard form helpers and BulletTrain's themed versions seamlessly.
# With standard Rails:
# form_with model: Post.new do |form|
# form.themed.text_field # Use BulletTrain theming on just one field
#
# form.themed.fields do # Need a nested section of fields but themed?
# end
# end
@kaspth
kaspth / object_proxy.rb
Created June 10, 2023 14:42
Making Ruby better at object proxying, so we don't need to add `user_name` etc. for Law of Demeter.
class Object::Proxy < SimpleDelegator
def initialize(object, **values)
super(object)
@values = values
end
def method_missing(name, ...)
@values.fetch(name) { super }
end
end
class Developer
has_object :search_scorer, after_save_commit: :rebuild_later # Forward callback onto context object.
end
# From my https://github.com/kaspth/active_record-associated_object gem.
# app/models/developer/search_scorer.rb
class Developer::SearchScorer < ActiveRecord::AssociatedObject
performs :rebuild # Adds `rebuild_later` to automatically generate a job to run the scoring calculation in.
def rebuild
record.update! search_score: new_score