Loading...
Loading...
Use when writing new Rails code for a project using the PostgreSQL + Hotwire + Tailwind CSS stack. Covers stack-specific patterns only: MVC structure, ActiveRecord query conventions, Turbo Frames/Streams wiring, Stimulus controllers, and Tailwind component patterns. Not for general Rails design principles — this skill is scoped to what changes based on this specific technology stack.
npx skill4agent add igmarin/rails-agent-skills rails-stack-conventionsALL new code MUST have its test written and validated BEFORE implementation.
1. Write the spec: bundle exec rspec spec/[path]_spec.rb
2. Verify it FAILS — output must show the feature does not exist yet
3. ONLY THEN write the implementation code
See rspec-best-practices for the full gate cycle.| Aspect | Convention |
|---|---|
| Style | RuboCop project config when present; otherwise Ruby Style Guide, single quotes |
| Models | MVC — service objects for complex logic, concerns for shared behavior |
| Queries | Eager load with |
| Frontend | Hotwire (Turbo + Stimulus); Tailwind CSS |
| Testing | RSpec with FactoryBot; TDD |
| Security | Strong params, guard XSS/CSRF/SQLi; Devise/Pundit for auth |
<%# Wrap a section to be replaced without a full page reload %>
<turbo-frame id="order-<%= @order.id %>">
<%= render "orders/details", order: @order %>
</turbo-frame>
<%# Link that targets only this frame %>
<%= link_to "Edit", edit_order_path(@order), data: { turbo_frame: "order-#{@order.id}" } %>respond_to do |format|
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
"order_#{@order.id}",
partial: "orders/order",
locals: { order: @order }
)
end
format.html { redirect_to @order }
end# BAD — triggers one query per order
@orders = Order.where(user: current_user)
@orders.each { |o| o.line_items.count }
# GOOD — single JOIN via includes
@orders = Order.includes(:line_items).where(user: current_user)# Controller stays thin — delegate to service
result = Orders::CreateOrder.call(user: current_user, params: order_params)
if result[:success]
redirect_to result[:order], notice: "Order created"
else
@order = Order.new(order_params)
render :new, status: :unprocessable_entity
end.callhtml_escaperawsanitize_sql| Mistake | Correct approach |
|---|---|
| Business logic in views | Use helpers, presenters, or Stimulus controllers |
| N+1 queries in loops | Eager load with |
| Raw SQL without parameterization | Use AR query methods or |
| Skipping FactoryBot for "quick" test | Fixtures are brittle — always use factories |
includes| Skill | When to chain |
|---|---|
| rails-code-conventions | For design principles, structured logging, and path-specific rules |
| rails-code-review | When reviewing existing code against these conventions |
| ruby-service-objects | When extracting business logic into service objects |
| rspec-best-practices | For testing conventions and TDD cycle |
| rails-architecture-review | For structural review beyond conventions |