Writing on web development, API integrations, and the payments industry.

Some of my long-form thoughts on programming, learning, productivity, and more, collected in chronological order.

Quick drag and drop sorting with Rails using stimulus and shopify/draggable

How to implement drag-and-drop sorting in Rails using StimulusJS and Shopify Draggable, setting up a Stimulus controller to handle drag events and send requests to update order on the server, with code samples showing how to configure the controller, use it in views, and process order updates on the backend to reorder associated models.

Rails Performance Playbook

In this Article, you will learn how to optimize the performance of Ruby on Rails applications. It covers backend optimization, tackling N+1 queries, caching, database indexing, DOM element reduction, lazy loading, and more. The article provides detailed explanations and recommendations for each optimization technique, helping you improve the efficiency and user experience of your Rails applications. Share your own tips and tricks by contacting the author via email.

Renaming in Rails Projects with `sed` and `find`: A Guide

Refactoring file and directory names, as well as their content, can be challenging, especially in large projects. This guide will walk you through the process using the sed and find commands, addressing common pitfalls and providing solutions to typical issues encountered during the refactor.

How to setup react-rails with esbuild

How to set up react-rails with esbuild and ultimately get server side rendering working so that we can use react-email.

Setting up PR previews for Rails on Render.com

Discusses the benefits of using PR-based workflows in software development and shares their experience setting up a staging environment for Rails on Render.com. A step-by-step guide on how to configure the staging environment, including creating a staging environment with Jumpstart Pro, setting up an Env group in Render, and configuring the `render.yaml` file. Also some sample bash scripts for the build, start, and initHook commands that use the `IS_PULL_REQUEST` environment variable set by Render to differentiate between production and staging environments.

Stripe Connect onboarding with Ruby on Rails

In this article, we learned how to integrate Stripe Connect onboarding with Ruby on Rails for a newsletter platform use case. We set up the necessary database models for representing authors, newsletters, their issues, and reader subscriptions. We also set up Stripe authentication, installed the Stripe Ruby SDK, and added the necessary code to create a Stripe Express account for authors. We also set up webhooks to listen for account updates and handle them to update the author's flags for whether charges and payouts are enabled. Finally, we tested the integration by going through the onboarding flow using test details and verified that the Stripe account is created successfully with the necessary flags enabled.

Handling webhooks for Stripe Connect

In this article, you'll learn how to use webhooks to automate parts of your Stripe Connect integration. We'll look at some node.js examples for handling webhook events in your server-side code, verifing webhook signatures for multiple use-cases, nesting verification to enable multiple webhook signing secrets. We'll also cover using the Stripe CLI to build and test your webhook endpoint.

Taking a cut with Stripe Connect

In this article, you'll learn how to collect a commission on payments flowing through your Stripe integration; take a cut from payments by transferring a smaller amount than the total payment; collect a one-time payment from a connected account; and collect recurring payments from your users as customers.

Picking the right charge type for your Stripe Connect platform

This blog post explores the different payment flow options in Stripe Connect, including Direct, Destination, and Separate Charges and Transfers (SCT). The article compares and contrasts the different flows, highlighting their key features, use cases, and potential pitfalls, and covers which connected account configurations work best with each funds flow. Whether you're a seasoned developer or new to Stripe Connect, this guide will give you the information you need to decide which payment flow suits your needs.

Standard vs. Express vs. Custom account types for Stripe Connect

When using Stripe Connect, you will need to create an account for each user of your platform who collects payments. There are three types of accounts to choose from: Standard, Express, and Custom. Standard accounts are the easiest to integrate and have the lowest operational overhead, while Custom accounts allow for more control over the user experience but require more development work to implement. It is recommended to use Stripe Connect Onboarding to onboard merchants and minimize compliance and operational issues. Standard and Express accounts receive automatic updates for new compliance requirements, while Custom accounts may need to make updates as compliance requirements change.

Pass data through Stripe payment links

Stripe Payment Links allow you to quickly get started with collecting payments. But passing data with your payment links can be tricky. Luckily, this blog post covers 3 ways to do it! Learn how to retrieve Checkout Sessions, use the `client_reference_id` query string parameter, and add UTM parameters to the query string. With these 3 tips you can easily track payments and build attribution for your campaigns with Stripe Payment Links.

How I start Django apps in 2022

This is mostly a note to self about the steps for setting up a fully operational django application with tailwind, authentication, and payments. ## Scaffold the python environment From some parent directory run: ```bash python -m venv venv so venv/bin/activate ``` Install django ```bash pip ...

Stripe API from Airtable Scripts

Airtable is a popular tool for building no-code applications. I’m finding that knowing just a little bit of JavaScript can really super charge these no-code solutions. [Airtable Scripting](https://www.airtable.com/developers/scripting) enables you to write a bit of custom JavaScript and wire that...

Handling Stripe Webhooks with Rails

This is mostly for my own reference later so I can quickly copy and paste snippets. First, I create a webhook controller: ```bash rails g controller Webhooks ``` Then, configure the routes to accept POST requests ```rb # config/routes.rb resources :webhooks, only: [:create] ``` Then, I make...

Tailwind UI menu with stimulus.js and Rails

Use a Stimulus controller to control the visibility of a Tailwind UI dropdown menu. You'll add an action to the button that toggles the `hidden` class, wire up the target for the controller, and add a `data-menu-target` to the content of the dropdown menu.

Rails with payments, auth, esbuild, and tailwind in 2022

Thank you for the update. The steps you provided for setting up a new Rails application in 2022 with authentication, payments, and emails are as follows: 1. Create a new Rails application with the necessary options: ```bash rails new pay-rails-demo -j esbuild -c tailwind -d postgresql -T --main cd pay-rails-demo ``` 2. Install the required dependencies: - NPM modules: ```bash npm i esbuild-darwin-arm64 ``` - Ruby gems: ```shell bundle add letter_opener -g development bundle add sidekiq bundle add stripe bundle add devise bundle add pay ``` 3. Set up the Node modules: - Set the desired Node version: ```shell nodenv local 16.13.1 ``` 4. Set up the build scripts in `package.json`: ```javascript "scripts": { "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds", "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify" } ``` 5. Set up the development runner in `Procfile.dev`: ```yml web: bin/rails server -p 3000 js: yarn build --watch css: yarn build:css --watch stripe: stripe listen --forward-to localhost:3000/pay/webhooks/stripe -c localhost:3000/pay/webhooks/stripe jobs: bundle exec sidekiq ``` 6. Finish setting up Rails configuration: - Set up Action Mailer and Active Job configuration in `config/environments/development.rb`: ```ruby # Mailers config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.delivery_method = :letter_opener config.action_mailer.perform_deliveries = true # Jobs config.active_job.queue_adapter = :sidekiq ``` - Create the database: ```shell bin/rails db:create ``` - Set up credentials for Stripe API keys and webhook signing secret: ```shell bin/rails credentials:edit --environment development ``` Add the following to the credentials file: ```yaml stripe: public_key: pk_test_... private_key: sk_test_... signing_secret: - whsec_... ``` Create an initializer for Stripe in `config/initializers/stripe.rb`: ```ruby Stripe.api_key = Rails.application.credentials.dig(:stripe, :private_key) ``` - Create a User model: ```shell bin/rails g model User ``` - Create a root controller: ```shell bin/rails g controller StaticPages root ``` Update `config/routes.rb` to set the root route: ```ruby root to: "static_pages#root" ``` 7. Add authentication with Devise: - Generate Devise files: ```shell bin/rails generate devise:install bin/rails generate devise User bin/rails generate devise:views ``` - Edit the migration file generated by Devise (`db/migrate/*_add_devise_to_users.rb`) to uncomment the `trackable` features. - Add the `trackable` attribute to the User model: ```ruby class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :trackable end ``` - Run the migrations: ```shell bin/rails db:migrate ``` - Add `before_action :authenticate_user!` to controllers where authentication is required. - Add the following view snippets to `application.html.erb` to display error messages: ```html <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> ``` - Update the Devise initializer (`config/initializers/devise.rb`) to enable `turbo_stream` format for navigational requests: ```ruby config.navigational_formats = ['*/*', :html, :turbo_stream] ``` - Allow logout via GET request to `/users/sign_out`: ```ruby config.sign_out_via = :get ``` 8. Add `Pay` payment processing: - Copy and run the migrations for `pay`: ```shell bin/rails pay:install:migrations bin/rails db:migrate ``` - Generate views for `pay` to customize email copy: ```shell bin/rails generate pay:views bin/rails generate pay:email_views ``` - Update the User model to include `pay_customer`: ```ruby class User < ApplicationRecord pay_customer( default_payment_processor: :stripe, stripe_attributes: :stripe_attributes ) def stripe_attributes(pay_customer) attrs = { metadata: { pay_customer_id: pay_customer.id, user_id: id } } if Rails.env.development? attrs[:test_clock] = Stripe::TestHelpers::TestClock.create( frozen_time: Time.now.to_i ) end attrs end end ``` That's it! You have now set up a Rails application with authentication, payments using `Pay`, and email functionality.

Creating a file with base64 png dataURL

This code snippet is a Ruby method that handles the creation of a file from base64-encoded data. Here's a breakdown of what it does: 1. It starts by extracting the base64-encoded content from the `params` object, specifically from `params["thumbnail"]["file"]['data:image/png;base64,'.length..-1]`. This removes the initial part of the string that indicates the file type and encoding. 2. It then decodes the base64 content using `Base64.decode64`, which is a Ruby method that decodes a base64-encoded string into its binary representation. 3. Next, it creates a `Tempfile` using `Tempfile.new([Time.now.to_i.to_s, ".png"])`. The `Tempfile` class in Ruby provides a temporary file that is automatically deleted when it is closed or when the Ruby process ends. 4. The binary content is then written to the `Tempfile` using `file.write(decoded_image)`. The `binmode` method is called to ensure that the file is opened in binary mode, which is necessary for handling binary data. 5. After writing the content to the `Tempfile`, the file pointer is rewound to the beginning using `file.rewind`. 6. At this point, you can perform any desired operations with the file, such as saving it to a storage service like ActiveStorage, which handles file uploads and attachments in Ruby on Rails. 7. Once the operations are completed, the `Tempfile` is closed using `file.close`, and then unlinked (i.e., deleted) using `file.unlink`. This removes the temporary file from the file system. 8. Finally, you can render or redirect the response according to your application's needs. Note that this code assumes that the input file is in PNG format, as indicated by the `'data:image/png;base64,'` prefix. If you expect different file formats, you will need to modify the code accordingly.