ruby
38 lines · 9 steps
Shaping API output with ActiveModel::Serializer in Rails
An ArticleSerializer defines exactly which fields, relations, and computed values an article exposes as JSON.
Explained by
highlit
1class ArticleSerializer < ActiveModel::Serializer
2 attributes :id, :title, :slug, :excerpt, :reading_time, :published_at, :url
3
4 belongs_to :author, serializer: UserSerializer
5 has_many :comments, if: :include_comments?
6 has_many :tags
7
8 meta do
9 { comment_count: object.comments.size }
10 end
11
12 def excerpt
13 object.body.truncate(200, separator: ' ')
14 end
15
16 def reading_time
17 minutes = (object.body.split.size / 200.0).ceil
18 "#{minutes} min read"
19 end
20
21 def published_at
22 object.published_at&.iso8601
23 end
24
25 def url
26 Rails.application.routes.url_helpers.article_url(object)
27 end
28
29 def include_comments?
30 instance_options[:with_comments] || current_user&.admin?
31 end
32
33 private
34
35 def current_user
36 scope
37 end
38end
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A serializer decouples your JSON shape from your database schema, so the API contract stays stable as models change.
- 2Overriding an attribute method lets you transform or compute values on the fly instead of exposing raw columns.
- 3Conditional associations and scope give you per-request, permission-aware output without branching in the controller.
Related explainers
ruby
class Product < ApplicationRecord scope :search, ->(query) { return all if query.blank?
Building a multi-term search scope in Rails
arel
scopes
full-text search
Advanced
7 steps
ruby
module Rack class MaintenanceMode RETRY_AFTER = 3600
A Rack maintenance-mode middleware in Rails
middleware
rack
http-status
Intermediate
8 steps
ruby
class ImageNormalizer ORIENTATION_TRANSFORMS = { 1 => ->(img) {}, 2 => ->(img) { img.flop },
Correcting EXIF orientation in Ruby
lookup-table
lambdas
image-processing
Intermediate
7 steps
ruby
module RequestTagging class Middleware def initialize(app) @app = app
Per-request context with CurrentAttributes in Rails
middleware
thread-safety
logging
Intermediate
7 steps
ruby
class Spellchecker ALPHABET = ('a'..'z').to_a.freeze def initialize(dictionary)
Building a Norvig-style spellchecker in Ruby
edit-distance
levenshtein
dynamic-programming
Advanced
10 steps
ruby
class Order < ApplicationRecord belongs_to :customer has_many :line_items has_many :products, through: :line_items
How scopes compose in a Rails model
scopes
activerecord
subqueries
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/shaping-api-output-with-activemodel-serializer-in-rails-explained-ruby-eb3d/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.