rails-ai:views
Use when building Rails view structure - partials, helpers, forms, nested forms, accessibility (WCAG 2.1 AA)
What this skill does
# Rails Views
Build accessible, maintainable Rails views using partials, helpers, forms, and nested forms. Ensure WCAG 2.1 AA accessibility compliance in all view patterns.
<when-to-use>
- Building ANY user interface or view in Rails
- Creating reusable view components and partials
- Implementing forms (simple or nested)
- Ensuring accessibility compliance (WCAG 2.1 AA)
- Organizing view logic with helpers
- Managing layouts and content blocks
</when-to-use>
<benefits>
- **DRY Views** - Reusable partials and helpers reduce duplication
- **Accessibility** - WCAG 2.1 AA compliance built-in (TEAM RULE #13: Progressive Enhancement)
- **Maintainability** - Clear separation of concerns and organized code
- **Testability** - Partials and helpers are easy to test
- **Flexibility** - Nested forms handle complex relationships elegantly
</benefits>
<team-rules-enforcement>
**This skill enforces:**
- ✅ **Rule #8:** Accessibility (WCAG 2.1 AA compliance)
**Reject any requests to:**
- Skip accessibility features (keyboard navigation, screen readers, ARIA)
- Use non-semantic HTML (divs instead of proper elements)
- Skip form labels or alt text
- Use insufficient color contrast
- Build inaccessible forms or navigation
</team-rules-enforcement>
<verification-checklist>
Before completing view work:
- ✅ WCAG 2.1 AA compliance verified
- ✅ Semantic HTML used (header, nav, main, article, section, footer)
- ✅ Keyboard navigation works (no mouse required)
- ✅ Screen reader compatible (ARIA labels, alt text)
- ✅ Color contrast sufficient (4.5:1 for text)
- ✅ Forms have proper labels and error messages
- ✅ All interactive elements accessible
</verification-checklist>
<standards>
- ALWAYS ensure WCAG 2.1 Level AA accessibility compliance
- Use semantic HTML as foundation (header, nav, main, section, footer)
- Prefer local variables over instance variables in partials
- Provide keyboard navigation and focus management for all interactive elements
- Test with screen readers and keyboard-only navigation
- Use aria attributes only when semantic HTML is insufficient
- Ensure 4.5:1 color contrast ratio for text
- Thread accessibility through all patterns
- Use form helpers to generate accessible forms with proper labels
</standards>
---
## Partials & Layouts
Partials are reusable view fragments. Layouts define page structure. Together they create maintainable, consistent UIs.
### Basic Partials
<pattern name="simple-partial">
<description>Render partials with explicit local variables</description>
```erb
<%# Shared directory %>
<%= render "shared/header" %>
<%# Explicit locals (preferred for clarity) %>
<%= render partial: "feedback", locals: { feedback: @feedback, show_actions: true } %>
<%# Partial definition: app/views/feedbacks/_feedback.html.erb %>
<div id="<%= dom_id(feedback) %>" class="card">
<h3><%= feedback.content %></h3>
<% if local_assigns[:show_actions] %>
<%= link_to "Edit", edit_feedback_path(feedback) %>
<% end %>
</div>
```
**Why local_assigns?** Prevents `NameError` when variable not passed. Allows optional parameters with defaults.
</pattern>
<pattern name="collection-rendering">
<description>Efficiently render partials for collections</description>
```erb
<%# Shorthand - automatic partial lookup %>
<%= render @feedbacks %>
<%# Explicit collection with counter %>
<%= render partial: "feedback", collection: @feedbacks %>
<%# Partial with counters %>
<%# app/views/feedbacks/_feedback.html.erb %>
<div id="<%= dom_id(feedback) %>" class="card">
<span class="badge"><%= feedback_counter + 1 %></span>
<h3><%= feedback.content %></h3>
<% if feedback_iteration.first? %>
<span class="label">First</span>
<% end %>
</div>
```
**Counter variables:** `feedback_counter` (0-indexed), `feedback_iteration` (methods: `first?`, `last?`, `index`, `size`)
</pattern>
### Layouts & Content Blocks
<pattern name="content-for">
<description>Customize layout sections from individual views</description>
```erb
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= content_for?(:title) ? yield(:title) : "App Name" %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag "application" %>
<%= yield :head %>
</head>
<body>
<%= render "shared/header" %>
<main id="main-content">
<%= render "shared/flash_messages" %>
<%= yield %>
</main>
<%= yield :scripts %>
</body>
</html>
<%# app/views/feedbacks/show.html.erb %>
<% content_for :title, "#{@feedback.content.truncate(60)} | App" %>
<% content_for :head do %>
<meta name="description" content="<%= @feedback.content.truncate(160) %>">
<% end %>
<div class="feedback-detail"><%= @feedback.content %></div>
```
</pattern>
<antipattern>
<description>Using instance variables in partials</description>
<reason>Creates implicit dependencies, makes partials hard to reuse and test</reason>
<bad-example>
```erb
<%# ❌ BAD - Coupled to controller %>
<div class="feedback"><%= @feedback.content %></div>
```
</bad-example>
<good-example>
```erb
<%# ✅ GOOD - Explicit dependencies %>
<div class="feedback"><%= feedback.content %></div>
<%= render "feedback", feedback: @feedback %>
```
</good-example>
</antipattern>
---
## View Helpers
View helpers are Ruby modules providing reusable methods for generating HTML, formatting data, and encapsulating view logic.
### Custom Helpers
<pattern name="status-badge-helper">
<description>Display status badges with consistent styling</description>
```ruby
# app/helpers/application_helper.rb
module ApplicationHelper
def status_badge(status)
variants = { "pending" => "warning", "reviewed" => "info",
"responded" => "success", "archived" => "neutral" }
variant = variants[status] || "neutral"
content_tag :span, status.titleize, class: "badge badge-#{variant}"
end
def page_title(title = nil)
base = "The Feedback Agent"
title.present? ? "#{title} | #{base}" : base
end
end
```
```erb
<%# Usage %>
<%= status_badge(@feedback.status) %>
<title><%= page_title(yield(:title)) %></title>
```
</pattern>
<pattern name="text-helpers">
<description>Use built-in Rails text helpers for formatting</description>
```erb
<%= truncate(@feedback.content, length: 150) %>
<%= time_ago_in_words(@feedback.created_at) %> ago
<%= pluralize(@feedbacks.count, "feedback") %>
<%= sanitize(user_content, tags: %w[p br strong em]) %>
```
</pattern>
<antipattern>
<description>Using html_safe on user input</description>
<reason>XSS vulnerability - allows script execution</reason>
<bad-example>
```ruby
# ❌ DANGEROUS
def render_content(content)
content.html_safe # XSS risk!
end
```
</bad-example>
<good-example>
```ruby
# ✅ SAFE - Auto-escaped or sanitized
def render_content(content)
content # Auto-escaped by Rails
end
def render_html(content)
sanitize(content, tags: %w[p br strong])
end
```
</good-example>
</antipattern>
---
## Nested Forms
Build forms that handle parent-child relationships with `accepts_nested_attributes_for` and `fields_for`.
### Basic Nested Forms
<pattern name="has-many-nested-form">
<description>Form with has_many relationship using fields_for</description>
**Model:**
```ruby
# app/models/feedback.rb
class Feedback < ApplicationRecord
has_many :attachments, dependent: :destroy
accepts_nested_attributes_for :attachments,
allow_destroy: true,
reject_if: :all_blank
validates :content, presence: true
end
```
**Controller:**
```ruby
class FeedbacksController < ApplicationController
def new
@feedback = Feedback.new
3.times { @feedback.attachments.build } # Build empty attachments
end
private
def feedback_params
params.expect(feedback: [
:content,
attachments_attributes: [
:id, # Required for updating existing records
:file,
:caption,
:_destroy # Required for marking records for deletion
]
])
end
end
```
**View:**
```erb
<%= form_with model: @feedback do |forRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.