Skip to content

Instantly share code, notes, and snippets.

View fractaledmind's full-sized avatar

Stephen Margheim fractaledmind

View GitHub Profile
@fractaledmind
fractaledmind / paper_trail_bug_patch.rb
Created April 6, 2023 08:40
This is the patch used to get around the bug reported with this gist: https://gist.github.com/fractaledmind/7574eaeb00dff6b9afd7778a7e024c19
# We need to patch PaperTrail to deal with Campaign having a `serialize` field that also has an `attribute` definition with a `default` value set for the attribute, as well as a database-level `default` set as well. For whatever all the reasons, PaperTrail tries to serialize the database-default, which is already a string. This throws an `ActiveRecord::SerializationTypeMismatch` error, as it is expecting the valued being serialized to be an `Array`. In this case, we can solve our problem by simply catching this error and checking of the value is already serialized.
module PaperTrail
module AttributeSerializers
class CastAttributeSerializer
private
def serialize(attr, val)
AttributeSerializerFactory.for(@klass, attr).serialize(val)
rescue ActiveRecord::SerializationTypeMismatch => error
if val.is_a?(String) && YAML.load(val)
@fractaledmind
fractaledmind / paper_trail_serialization_bug_report.rb
Created April 6, 2023 08:38
This bug report script demonstrates a bug with PaperTrail when the ActiveRecord model has both database and model defaults for a serialized field
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "activerecord", "~> 7.0.0"
@fractaledmind
fractaledmind / on_object_merged_job.rb
Last active March 31, 2023 14:27
Refactor of https://twitter.com/_swanson/status/1641800267329941507?s=20 to demonstrate what a job-centric approach would look like.
# app/jobs/hubspot/webhooks/on_object_merged_job.rb
class Hubspot::Webhooks::OnObjectMergedJob < ApplicationJob
def perform(portal_id:, object_type:, merged_object_ids:, new_object_id:)
integration = Integration.find_by(source: :hubspot, uid: portal_id)
return unless integration.present?
integration
.organization
.integration_proxies
.where(
@fractaledmind
fractaledmind / application.rb
Last active June 6, 2024 16:41
Create a simple, beautiful Rails-integrated multi-file input that behaves like: https://codepen.io/smargh/pen/mdGLpEz. Uses TailwindCSS, StimulusJS, and ActiveStorage.
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
# ensure that `update(files: [uploaded_file])` will append, not replace
config.active_storage.replace_on_assign_to_many = false
end
@fractaledmind
fractaledmind / flatten_keys_of.rb
Last active February 17, 2023 08:16
Returns a flat hash where all nested keys are flattened into an array of keys.
# frozen_string_literal: true
# Returns a flat hash where all nested keys are flattened into an array of keys.
#
# hash = { key: 'value', nested: { key: 'nested_value' }, array: [0, 1, 2] }
# flatten_keys_of(hash)
# => { [:key]=>"value", [:nested, :key]=>"nested_value", [:array]=>[0, 1, 2] }
#
# Can also pass a Proc to change how nested keys are flattened:
# flatten_keys_of(hash, flattener: ->(*keys) { keys.join('.') })
class JobRun < ActiveRecord::Base
FINISHED_RECOVERY_POINT = "FINISHED"
validates :job_class, presence: true
validates :job_id, presence: true
validates :serialized_job, presence: true
serialize :serialized_job, JSON
store :persisted_data
class DetailsPopoverComponent < ApplicationComponent
class InvalidSide < StandardError
def initialize(side)
super("`#{side}` must be one of `top`, `bottom`, `left`, or `right`")
end
end
class InvalidAlign < StandardError
def initialize(align)
super("`#{align}` must be one of `start`, `center`, or `end`")
end
@fractaledmind
fractaledmind / artifact_interface_concern.rb
Created September 9, 2022 17:27
Ruby on Rails model interfaces
# frozen_string_literal: true
module ArtifactInterface
extend ActiveSupport::Concern
extend Interfaceable
def key
raise NotImplementedError
end
@fractaledmind
fractaledmind / api_auto_pagination.rb
Created May 13, 2022 12:00
Generalized auto_paginate method to work with GitHub, Jira, and Slack APIs
require "httpx"
module Clientable
extend ActiveSupport::Concern
def initialize
@httpx = HTTPX
.plugin(:retries, retry_change_requests: true)
.max_retries(3)
end
@fractaledmind
fractaledmind / snapshotable.rb
Last active October 7, 2022 08:30
ActiveRecord Concern to mark a slice of a model's association tree as freezable, to freeze it at some point, and then to work with frozen versions of those objects moving forward
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Activate the gem you are reporting the issue against.