Claude-skill-registry inertia-rails
Building full-stack applications with Inertia.js in Rails using React. Use when working with Inertia responses, forms, props, redirects, React page components, or Rails controllers in an Inertia project.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/inertia-rails" ~/.claude/skills/majiayu000-claude-skill-registry-inertia-rails && rm -rf "$T"
skills/data/inertia-rails/SKILL.mdInertia Rails
What is Inertia Rails
Inertia Rails is a hybrid approach that combines Rails server-side routing with React client-side views. It's not a traditional SPA (no client-side routing) and not traditional SSR (no server-side rendering).
How it works:
- Rails handles routing, controllers, authentication, data fetching
- React components replace ERB templates as the view layer
- Inertia intercepts link clicks and makes XHR requests
- Server returns JSON with component name and props instead of HTML
- Client dynamically swaps components without full page reload
Component location:
app/frontend/pages/ControllerName/ActionName.jsx
Responses & Props
Basic Inertia Response
# Automatic component resolution: users/show.jsx def show user = User.find(params[:id]) render inertia: { user: } end
Explicit Component Names
def my_event event = Event.find(params[:id]) render inertia: 'events/show', props: { event: } end
View Data for ERB Templates
def show event = Event.find(params[:id]) render inertia: { event: }, view_data: { meta: event.meta } end
⚠️ Security Warning: All props are visible client-side. Never include sensitive data in props.
Redirects
Always redirect after form submissions. Inertia automatically handles 303 responses.
def create user = User.new(user_params) if user.save redirect_to users_url else redirect_to new_user_url, inertia: { errors: user.errors } end end
External Redirects
Use
inertia_location for external URLs or non-Inertia endpoints:
inertia_location external_service_url
Forms
Form Component
Use
<Form> for simple forms that behave like HTML forms:
import { Form } from '@inertiajs/react' <Form action="/users" method="post"> <input type="text" name="name" /> <input type="email" name="email" /> <button type="submit">Create User</button> </Form>
Key props:
,action
: Form endpointmethod
: Reset form after successful submissionresetOnSuccess
: Modify data before submissiontransform
,onSuccess
: Event callbacksonError
Slot props for state:
<Form action="/users" method="post"> {({ errors, processing, wasSuccessful }) => ( <> <input type="text" name="name" /> {errors.name && <div>{errors.name}</div>} <button type="submit" disabled={processing}> {processing ? 'Creating...' : 'Create User'} </button> {wasSuccessful && <div>User created!</div>} </> )} </Form>
useForm Helper
Use
useForm for programmatic control and complex forms:
import { useForm } from '@inertiajs/react' const { data, setData, post, processing, errors, reset } = useForm({ name: '', email: '', }) function submit(e) { e.preventDefault() post('/users', { onSuccess: () => reset('password'), }) } return ( <form onSubmit={submit}> <input value={data.name} onChange={(e) => setData('name', e.target.value)} /> {errors.name && <div>{errors.name}</div>} <button type="submit" disabled={processing}>Submit</button> </form> )
Key methods:
,get
,post
,put
,patch
: Submit formdelete
: Update form datasetData
: Reset to default valuesreset
: Clear validation errorsclearErrors
: Manually set errorssetError
Validation Errors
Rails automatically populates errors when validation fails:
# Controller - errors automatically available in frontend def create user = User.new(user_params) if user.save redirect_to users_url else redirect_to new_user_url, inertia: { errors: user.errors } end end
Deferred & Lazy Props
Server-side Deferred Props
Use
InertiaRails.defer for data that loads after initial render:
def index render inertia: { users: -> { User.all }, permissions: InertiaRails.defer { Permission.all }, } end
Client-side Deferred Component
import { Deferred } from '@inertiajs/react' <Deferred data="permissions" fallback={<div>Loading...</div>}> <PermissionsComponent /> </Deferred>
WhenVisible for Lazy Loading
import { WhenVisible } from '@inertiajs/react' <WhenVisible data="permissions" fallback={<div>Loading...</div>}> <PermissionsComponent /> </WhenVisible>
Navigation
Link Component
Replace
<a> with <Link> for Inertia navigation:
import { Link } from '@inertiajs/react' <Link href="/users">Users</Link> <Link href="/users/new" method="post" as="button">New User</Link>
Programmatic Navigation
import { router } from '@inertiajs/react' router.visit('/users') router.post('/users', data) router.visit('/users', { only: ['users'] }) // Partial reload
Flash Messages
Setting Flash Messages
def create user = User.new(user_params) if user.save redirect_to users_url, notice: 'User created successfully!' else redirect_to new_user_url, inertia: { errors: user.errors, alert: 'Failed to create user' } end end
Accessing Flash Messages
Flash messages are automatically available as props:
// In your layout or page component export default function Layout({ children, flash }) { return ( <div> {flash.notice && <div className="notice">{flash.notice}</div>} {flash.alert && <div className="alert">{flash.alert}</div>} {children} </div> ) }
Routes
Shorthand Routes
Route directly to components without controllers:
# config/routes.rb inertia 'dashboard' => 'Dashboard' inertia :settings # Maps to Settings component namespace :admin do inertia 'dashboard' => 'Admin/Dashboard' end resources :users do inertia :activity, on: :member end
URL Generation
Generate URLs server-side and include as props:
def index render inertia: { users: User.all.map { |user| user.as_json(only: [:id, :name]).merge(edit_url: edit_user_path(user)) }, create_url: new_user_path } end