Alba::Inertia
Seamless integration between Alba serializers and Inertia Rails.
Features
- Support for all Inertia prop types: optional, deferred, and merge props
- Lazy evaluation for efficient data loading on partial reloads
- Auto-detection of resource classes based on controller/action naming
Installation
Add to your Gemfile:
gem "alba"
gem "inertia_rails"
gem "alba-inertia"Usage
Basic Setup
Include Alba::Inertia::Resource in your resource classes:
class ApplicationResource
include Alba::Resource
# ...
helper Alba::Inertia::Resource
endInclude Alba::Inertia::Controller in your controllers:
class InertiaController < ApplicationController
include Alba::Inertia::Controller
endDefining Inertia Props
Inline inertia: option (recommended)
class CoursesIndexResource < ApplicationResource
# Simple attributes
attributes :id, :title
# Optional prop (loaded only when requested)
has_many :courses, serializer: CourseResource, inertia: :optional
# Deferred prop (loaded in separate request)
has_many :students, serializer: StudentResource, inertia: :defer
# Deferred with options
attribute :stats, inertia: { defer: { group: 'analytics', merge: true } } do |object|
expensive_calculation(object)
end
# Merge prop (for partial reloads)
has_many :comments, serializer: CommentResource, inertia: { merge: { match_on: :id } }
# Scroll prop with auto-detection.
# Checks object for `scroll_meta` and `pagy` attributes, or object being a Kaminari collection.
has_many :items, inertia: :scroll
# Scroll prop with explicit metadata
has_many :items, inertia: { scroll: :meta }
has_many :items, inertia: { scroll: ->(obj) { obj.meta } }
has_many :items, inertia: { scroll: ->(obj) { obj.meta }, wrapper: 'data' }
# Once prop
has_many :plans, inertia: :once
has_many :plans, inertia: { once: { key: 'active_plans', expires_in: 1.hour, fresh: ->(obj) { obj.fresh? } } }
endSeparate inertia_prop declaration
class CoursesIndexResource < ApplicationResource
has_many :courses, serializer: CourseResource
inertia_prop :courses, optional: true
attribute :stats
inertia_prop :stats, defer: { merge: true, group: 'analytics' }
endController Integration
class CoursesController < InertiaController
def index
@courses = Course.all
@current_category_id = params[:category_id]
# Auto-detects CoursesIndexResource and passes instance variables
end
def show
@course = Course.find(params[:id])
# With a custom component
render_inertia "Courses/Show"
end
def create
@course = Course.new(course_params)
if @course.save
redirect_to courses_path
else
# With errors
render_inertia inertia: { errors: user.errors }
end
end
endSerialization Modes
.to_inertia - For Inertia.js rendering
Returns lazy procs and Inertia prop objects:
resource = CoursesIndexResource.new(courses: @courses)
resource.to_inertia
# => { "courses" => <InertiaRails::OptionalProp>, "stats" => <Proc> }
.as_json - For standard JSON
Returns normal data (Typelizer, API endpoints):
resource = CoursesIndexResource.new(courses: @courses)
resource.as_json
# => { "courses" => [...], "stats" => 42 }Inheritance
Metadata is inherited from parent resources:
class BaseResource < ApplicationResource
attribute :created_at, inertia: :optional
end
class CourseResource < BaseResource
attributes :id, :title
# Inherits created_at with optional: true
endChild can override parent metadata:
class ExtendedCourseResource < CourseResource
inertia_prop :created_at, defer: true # Override parent's optional: true
endConfiguration
Alba::Inertia.configure do |config|
# Render with Alba resource class by default
config.default_render = true
# Wrap all props in lambdas by default
config.lazy_by_default = true
endAdvanced Usage
Custom Serializer Selection
render_inertia(serializer: CustomResource)Custom Props
render_inertia(locals: { custom: 'props'})Serializer Params
You can pass params to the serializer using the serializer_params option. This is useful for passing context like the current user, permissions, or feature flags:
class CoursesController < InertiaController
def index
@courses = Course.all
render_inertia(serializer_params: { current_user: current_user })
end
endIn your resource, access params via the params method:
class CoursesIndexResource < ApplicationResource
attributes :id, :title
attribute :can_edit do |course|
params[:current_user]&.can_edit?(course)
end
endDefault Serializer Params
Override inertia_serializer_params in your controller to provide default params for all Inertia renders:
class ApplicationController < ActionController::Base
include Alba::Inertia::Controller
private
def inertia_serializer_params
{ current_user: current_user, locale: I18n.locale }
end
endThe serializer_params option in render_inertia will be merged with these defaults (with serializer_params taking precedence).
Naming Convention
The controller integration follows Rails conventions:
# Controller: CoursesController
# Action: index
# Expected Resource: CoursesIndexResource or CoursesIndexSerializer
# Controller: Admin::UsersController
# Action: show
# Expected Resource: Admin::UsersShowResource or Admin::UsersShowSerializerDevelopment
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/skryukov/alba-inertia.
License
The gem is available as open source under the terms of the MIT License.