# Basic Ractor usage
ractor = Ractor.new do
# This runs in parallel, isolated from main thread
result = heavy_computation
result
end
class PostsController < ApplicationController
def create
@post = current_member.posts.build(post_params)
if @post.save
redirect_to @post, status: :see_other
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
belongs_to :author, class_name: "User"
scope :visible, -> { where(deleted_at: nil).order(:created_at) }
<%= turbo_stream_from [Current.account, :notifications] %>
<div id="notifications"></div>
class Current < ActiveSupport::CurrentAttributes
attribute :user, :tenant, :request_id, :ip_address
def user_display
user&.email || "system"
end
module Paginatable
extend ActiveSupport::Concern
included do
before_action :set_pagination_params, only: [:index]
end
class CreatePostService
def initialize(author:, params:)
@author = author
@params = params
end
# Gemfile
gem 'graphql'
# Installation
# rails generate graphql:install
user = User.find_by(email: params[:email].to_s.downcase.strip)
if user
raw_token = SecureRandom.urlsafe_base64(32)
user.password_resets.create!(token_digest: Digest::SHA256.hexdigest(raw_token), expires_at: 30.minutes.from_now)
PasswordResetMailer.with(user: user, token: raw_token).deliver_later
allowed_types = ['image/png', 'image/jpeg', 'application/pdf']
uploaded = params.require(:document)
raise ActionController::BadRequest, 'file too large' if uploaded.size > 10.megabytes
raise ActionController::BadRequest, 'type not allowed' unless allowed_types.include?(uploaded.content_type)
class AddStatusToPosts < ActiveRecord::Migration[6.1]
# Use change for automatic rollback
def change
# Add column without default to avoid table lock
add_column :posts, :status, :string
production:
primary:
adapter: postgresql
url: <%= ENV['DATABASE_URL'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5) %>
primary_replica: