Skip to content

Instantly share code, notes, and snippets.

View ayrton's full-sized avatar

Ayrton ayrton

View GitHub Profile
@chaance
chaance / root.tsx
Created March 11, 2023 00:32
Remove trailing slashes to URL via redirect in Remix
import { redirect, type LoaderArgs } from "@remix-run/node";
export async function removeTrailingSlashes(request: Request) {
let url = new URL(request.url);
if (url.pathname.endsWith("/") && url.pathname !== "/") {
throw redirect(url.pathname.slice(0, -1) + url.search);
}
}
export async function loader({ request }: LoaderArgs) {
@palkan
palkan / mailers_preview_spec.rb
Created July 8, 2022 16:15
mailers_preview_spec.rb
# frozen_string_literal: true
require "rails_helper"
# Automatically smoke-test all mailer previews
describe "/rails/mailers" do
subject { response }
ActionMailer::Preview.all.each do |preview|
next if preview.emails.empty?
@kaspth
kaspth / scope_with_class_methods.rb
Created July 1, 2022 11:22
`scope` extension to allow marking a class method as a scope.
# In Active Record, class method scopes have to remember to return `all` otherwise they're break the call chain.
#
# def self.some_scope = nil # Assume more complex conditions that would result in a branch that accidentally didn't return `all`.
#
# User.some_scope.first # => raises NoMethodError `first' for NilClass
#
# Note: Active Record ensures a `scope :some_scope, -> { nil }` returns `all` via `|| all` here:
# https://github.com/rails/rails/blob/c704da66de59262f4e88824589ae4eddefb6ed4a/activerecord/lib/active_record/scoping/named.rb#L181
#
# Now, this extension allows you to mark a class method as a scope, so you don't have to remember and the code is more clearly demarcated too.
@joeldrapper
joeldrapper / attribute_memoization.rb
Last active December 13, 2022 12:24
Attribute Memoization
module AttributeMemoization
def attr_accessor(*names, &block)
return super(*names) unless block_given?
attr_reader(*names, &block)
attr_writer(*names)
end
def attr_reader(*names, &block)
return super(*names) unless block_given?
/* https://go.tacodewolff.nl/minify */
enScroll=!1,enFdl=!1,extCurrent=void 0,filename=void 0,targetText=void 0,splitOrigin=void 0;const lStor=localStorage,sStor=sessionStorage,doc=document,docEl=document.documentElement,docBody=document.body,docLoc=document.location,w=window,s=screen,nav=navigator||{},extensions=["pdf","xls","xlsx","doc","docx","txt","rtf","csv","exe","key","pps","ppt","pptx","7z","pkg","rar","gz","zip","avi","mov","mp4","mpe","mpeg","wmv","mid","midi","mp3","wav","wma"];function a(e,t,n,o){const j="G-XXXXXXXXXX",r=()=>Math.floor(Math.random()*1e9)+1,c=()=>Math.floor(Date.now()/1e3),F=()=>(sStor._p||(sStor._p=r()),sStor._p),E=()=>r()+"."+c(),_=()=>(lStor.cid_v4||(lStor.cid_v4=E()),lStor.cid_v4),m=lStor.getItem("cid_v4"),v=()=>m?void 0:enScroll==!0?void 0:"1",p=()=>(sStor.sid||(sStor.sid=c()),sStor.sid),O=()=>{if(!sStor._ss)return sStor._ss="1",sStor._ss;if(sStor.getItem("_ss")=="1")return void 0},a="1",g=()=>{if(sStor.sct)if(enScroll==!0)return sStor.sct;else x=+sStor.getItem("sct")+ +a,sSto
@julianrubisch
julianrubisch / script.rb
Last active February 18, 2022 12:03
ActiveStorage DirectUpload via Faraday
require "faraday"
require "faraday/multipart"
token = ARGV.shift
absolute_path = File.expand_path(ARGV.shift)
# TODO how could we require "active_storage/blob" without eager loading the whole app
blob = ActiveStorage::Blob.build_after_unfurling(io: File.open(absolute_path), filename: File.basename(absolute_path))
@kentcdodds
kentcdodds / jokes.md
Created November 22, 2021 17:34
Headers and caching section removed from the Remix Tutorial because it was too long.

Headers and Caching

Caching is a big subject and it can get pretty complicated. Luckily, the browsers have done all the really hard work for us and we just need to #useThePlatform.

There are three types of caches you'll likely deal with in Remix applications:

  1. Application-level caches that you implement in your own code.
  2. Browser caches you can control through the Cache-Control header.
  3. CDN caches you also can control through the Cache-Control headers.
@OliverJAsh
OliverJAsh / doc.md
Created June 22, 2021 11:32
Unsplash: Architectural Decision Record (ADR): Mocking API requests in E2E (Cypress) tests

Mocking API requests in E2E (Cypress) tests

Problem

Testing at the network level

In our E2E tests, when the test runner navigates through the site, we don't want to make real API requests but rather we want to mock these requests so that we can easily test many different scenarios, and so that our tests are more resilient and less likely to flake if API is suffering any downtime.

Up until now, this has been achieved by "mocking the fetch function". For example:

@ItsWendell
ItsWendell / segment-analytics.ts
Last active January 30, 2023 10:36
Segment Analytics client for Lambda with Fire & Forget support.
import { merge } from "lodash";
import { request } from "https";
import { v4 as uuidv4 } from "uuid";
export const name = "analytics-lamdba";
export const version = "0.1.2";
export type SegmentMessageTypes =
| "identify"
| "group"
@wilsonpage
wilsonpage / swr.ts
Last active July 18, 2024 20:41
An implementation of stale-while-revalidate for Cloudflare Workers
export const CACHE_STALE_AT_HEADER = 'x-edge-cache-stale-at';
export const CACHE_STATUS_HEADER = 'x-edge-cache-status';
export const CACHE_CONTROL_HEADER = 'Cache-Control';
export const CLIENT_CACHE_CONTROL_HEADER = 'x-client-cache-control';
export const ORIGIN_CACHE_CONTROL_HEADER = 'x-edge-origin-cache-control';
enum CacheStatus {
HIT = 'HIT',
MISS = 'MISS',
REVALIDATING = 'REVALIDATING',