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)
class ActiveRecord::Relation::Loaded < Data.define(:records) | |
def where(**conditions) | |
records = @records.dup | |
conditions.each do |key, value| | |
records.select! { |record| record.send(key) == value } | |
end | |
with(records:) | |
end | |
# Not sure how to maintain the order of the passed in keys? |
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:") |
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 |
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)
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 |
# 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 |
class Object::Proxy < SimpleDelegator | |
def initialize(object, **values) | |
super(object) | |
@values = values | |
end | |
def method_missing(name, ...) | |
@values.fetch(name) { super } | |
end | |
end |