class Document < ApplicationRecord
belongs_to :owner, class_name: "User"
has_many :visibilities, class_name: "DocumentVisibility", dependent: :delete_all
scope :public_documents, -> { where(is_public: true) }
scope :visible_to, ->(actor) do
DocumentVisibilityQuery.new(self, actor).relation
end
def grant_to(subject)
visibilities.create!(subject: subject)
end
end
class DocumentVisibility < ApplicationRecord
belongs_to :document
belongs_to :subject, polymorphic: true
end
class DocumentVisibilityQuery
def initialize(scope, actor)
@scope = scope
@actor = actor
end
def relation
@scope.where(public_condition.or(owner_condition).or(shared_condition)) end
private
def docs
Document.arel_table
end
def vis
DocumentVisibility.arel_table
end
def public_condition
docs[:is_public].eq(true)
end
def owner_condition
docs[:owner_id].eq(@actor.id)
end
def shared_condition
principals = principal_pairs
return docs[:id].eq(nil) if principals.empty?
matches = principals.map do |type, id|
vis[:subject_type].eq(type).and(vis[:subject_id].eq(id))
end.reduce(:or)
subquery = Arel::SelectManager.new
subquery.from(vis)
subquery.project(Arel.sql("1"))
subquery.where(vis[:document_id].eq(docs[:id]).and(matches))
Arel::Nodes::Exists.new(subquery)
end
def principal_pairs
pairs = [["User", @actor.id]]
Array(@actor.try(:team_ids)).each { |tid| pairs << ["Team", tid] }
pairs
end
end
class DocumentsController < ApplicationController
before_action :authenticate_user!
def index
@documents = Document
.visible_to(current_user)
.merge(search_scope)
.order(updated_at: :desc)
.page(params[:page])
render :index
end
def show
@document = Document.visible_to(current_user).find(params[:id])
render :show
rescue ActiveRecord::RecordNotFound
head :not_found
end
private
def search_scope
return Document.all if params[:q].blank?
Document.where("title ILIKE ?", "%#{params[:q]}%")
end
end
This snippet shows how to build a reusable visible_to scope that answers a common authorization question — "which records is this actor allowed to see?" — when visibility can come from several different sources at once. Rather than filtering in Ruby after loading rows, the logic is pushed down into a single SQL query composed with Arel, so pagination, counting, and further chaining all stay correct and efficient.
The Document model defines the domain: a document can be public, owned directly by a user, or shared through a polymorphic visibilities association whose subject is either a User or a Team. The visible_to scope delegates to a query object so the model stays thin, and it accepts any actor that can describe its own visibility principals via team_ids.
The interesting work lives in DocumentVisibilityQuery. It builds three independent Arel predicates against the documents and document_visibilities tables: public_condition matches anything flagged public, owner_condition matches the actor's own rows, and shared_condition matches a polymorphic grant using both subject_type and subject_id. Building the EXISTS subquery with Arel::SelectManager keeps the correlation (vis[:document_id].eq(docs[:id])) explicit and avoids an accidental cartesian join. Combining the pieces with or produces one predicate, which is handed to ActiveRecord via where(condition) — so the caller still gets a normal, chainable ActiveRecord::Relation.
Using Arel here rather than string interpolation matters: table and column references go through arel_table, values are bound as parameters, and the subject_type/subject_id pair is matched together, which is exactly the trap that makes naive polymorphic queries leak rows across types. The EXISTS form also short-circuits per document and plays well with a composite index on (subject_type, subject_id, document_id).
The DocumentsController shows the payoff at the call site. Document.visible_to(current_user) is used as an ordinary scope, then merged with search and pagination without any special casing, and the same scope is reused to authorize a single show lookup so the read path can never diverge from the list path. The trade-off is that Arel is verbose and version-sensitive; the benefit is one authoritative, index-friendly definition of visibility that is impossible to bypass by loading first and filtering later.
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
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
Share this code
Here's the card — post it anywhere.