Seamless integration between Alba serializers and Inertia Rails.
- 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
Add to your Gemfile:
gem "alba"
gem "inertia_rails"
gem "alba-inertia"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
endclass 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? } } }
endclass CoursesIndexResource < ApplicationResource
has_many :courses, serializer: CourseResource
inertia_prop :courses, optional: true
attribute :stats
inertia_prop :stats, defer: { merge: true, group: 'analytics' }
endclass 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
endReturns lazy procs and Inertia prop objects:
resource = CoursesIndexResource.new(courses: @courses)
resource.to_inertia
# => { "courses" => <InertiaRails::OptionalProp>, "stats" => <Proc> }Returns normal data (Typelizer, API endpoints):
resource = CoursesIndexResource.new(courses: @courses)
resource.as_json
# => { "courses" => [...], "stats" => 42 }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
endAlba::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
endrender_inertia(serializer: CustomResource)render_inertia(locals: { custom: 'props'})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
endOverride 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).
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::UsersShowSerializerAfter 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.
Bug reports and pull requests are welcome on GitHub at https://github.com/skryukov/alba-inertia.
The gem is available as open source under the terms of the MIT License.