# Alba::Inertia [![Gem Version](https://badge.fury.io/rb/alba-inertia.svg)](https://rubygems.org/gems/alba-inertia) Seamless integration between [Alba](https://github.com/okuramasafumi/alba) serializers and [Inertia Rails](https://inertia-rails.dev/). ## 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
Evil Martians logo Alba::Inertia is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups. ## Installation Add to your Gemfile: ```ruby gem "alba" gem "inertia_rails" gem "alba-inertia" ``` ## Usage ### Basic Setup Include `Alba::Inertia::Resource` in your resource classes: ```ruby class ApplicationResource include Alba::Resource # ... helper Alba::Inertia::Resource end ``` Include `Alba::Inertia::Controller` in your controllers: ```ruby class InertiaController < ApplicationController include Alba::Inertia::Controller end ``` ### Defining Inertia Props #### Inline `inertia:` option (recommended) ```ruby 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? } } } end ``` #### Separate `inertia_prop` declaration ```ruby class CoursesIndexResource < ApplicationResource has_many :courses, serializer: CourseResource inertia_prop :courses, optional: true attribute :stats inertia_prop :stats, defer: { merge: true, group: 'analytics' } end ``` ### Controller Integration ```ruby 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 end ``` ### Serialization Modes #### `.to_inertia` - For Inertia.js rendering Returns lazy procs and Inertia prop objects: ```ruby resource = CoursesIndexResource.new(courses: @courses) resource.to_inertia # => { "courses" => , "stats" => } ``` #### `.as_json` - For standard JSON Returns normal data (Typelizer, API endpoints): ```ruby resource = CoursesIndexResource.new(courses: @courses) resource.as_json # => { "courses" => [...], "stats" => 42 } ``` ### Inheritance Metadata is inherited from parent resources: ```ruby class BaseResource < ApplicationResource attribute :created_at, inertia: :optional end class CourseResource < BaseResource attributes :id, :title # Inherits created_at with optional: true end ``` Child can override parent metadata: ```ruby class ExtendedCourseResource < CourseResource inertia_prop :created_at, defer: true # Override parent's optional: true end ``` ## Configuration ```ruby 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 end ``` ## Advanced Usage ### Custom Serializer Selection ```ruby render_inertia(serializer: CustomResource) ``` ### Custom Props ```ruby 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: ```ruby class CoursesController < InertiaController def index @courses = Course.all render_inertia(serializer_params: { current_user: current_user }) end end ``` In your resource, access params via the `params` method: ```ruby class CoursesIndexResource < ApplicationResource attributes :id, :title attribute :can_edit do |course| params[:current_user]&.can_edit?(course) end end ``` ### Default Serializer Params Override `inertia_serializer_params` in your controller to provide default params for all Inertia renders: ```ruby class ApplicationController < ActionController::Base include Alba::Inertia::Controller private def inertia_serializer_params { current_user: current_user, locale: I18n.locale } end end ``` The `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: ```ruby # Controller: CoursesController # Action: index # Expected Resource: CoursesIndexResource or CoursesIndexSerializer # Controller: Admin::UsersController # Action: show # Expected Resource: Admin::UsersShowResource or Admin::UsersShowSerializer ``` ## Development 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](https://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](https://opensource.org/licenses/MIT).