class TransferFundsService
def initialize(from_account:, to_account:, amount:)
@from_account = from_account
@to_account = to_account
@amount = amount
end
def call
ActiveRecord::Base.transaction do
# Lock rows to prevent concurrent modifications
from = Account.lock.find(@from_account.id)
to = Account.lock.find(@to_account.id)
raise InsufficientFundsError if from.balance < @amount
from.update!(balance: from.balance - @amount)
to.update!(balance: to.balance + @amount)
Transaction.create!(
from_account: from,
to_account: to,
amount: @amount,
status: 'completed'
)
end
Result.success
rescue InsufficientFundsError => e
Result.failure(error: 'INSUFFICIENT_FUNDS')
rescue StandardError => e
Rails.logger.error("TransferFundsService failed: #{e.message}")
Result.failure(error: 'TRANSFER_FAILED')
end
end
Transactions ensure that multiple database operations either all succeed or all fail together, preventing partial updates that leave data in inconsistent states. Rails provides ActiveRecord::Base.transaction which wraps a block of code in a database transaction. If any exception is raised within the block, all changes are rolled back automatically. This is critical for operations like transferring funds, creating orders with line items, or any workflow where related records must remain synchronized. I'm careful to keep transaction blocks focused and fast—long-running operations or external API calls inside transactions can cause lock contention and deadlocks. For complex workflows, I use database-level constraints as a second line of defense against invariant violations.
Related snips
class CommentsController < ApplicationController
before_action :set_post
def create
@comment = @post.comments.build(comment_params)
System test: asserting Turbo Stream responses
class Post < ApplicationRecord
belongs_to :author, class_name: 'User'
has_many :comments, dependent: :destroy
scope :published, -> { where.not(published_at: nil).where('published_at <= ?', Time.current) }
scope :draft, -> { where(published_at: nil) }
ActiveRecord scopes for reusable query logic
module Api
module V1
class UsersController < BaseController
def show
user = User.includes(:profile).find(params[:id])
ETags for conditional requests and caching
class PostsController < ApplicationController
def index
@posts = Post.includes(:author)
.order(created_at: :desc)
.page(params[:page])
.per(10)
Turbo Frames: infinite scroll with lazy-loading frame
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
<form data-controller="query-sync" data-action="change->query-sync#apply">
<select name="status" class="rounded border p-2">
<option value="">Any</option>
<option value="open">Open</option>
<option value="closed">Closed</option>
</select>
Filter UI that syncs query params via Stimulus (no front-end router)
Share this code
Here's the card — post it anywhere.