rails-ai:models
Use when designing Rails models - ActiveRecord patterns, validations, callbacks, scopes, associations, concerns, query objects, form objects
What this skill does
# Models
Master Rails model design including ActiveRecord patterns, validations, callbacks, scopes, associations, concerns, custom validators, query objects, and form objects.
<when-to-use>
- Designing database models and associations
- Writing validations and callbacks
- Implementing business logic in models
- Creating scopes and query methods
- Extracting complex queries to query objects
- Building form objects for multi-model operations
- Organizing shared behavior with concerns
- Creating custom validators
- Preventing N+1 queries
</when-to-use>
<benefits>
- **Convention Over Configuration** - Minimal setup for maximum functionality
- **Single Responsibility** - Each pattern handles one concern
- **Reusability** - Share behavior across models with concerns
- **Testability** - Test models, concerns, validators in isolation
- **Query Optimization** - Built-in N+1 prevention and eager loading
- **Type Safety** - ActiveModel::Attributes provides type casting
- **Database Agnostic** - Works with PostgreSQL, MySQL, SQLite
</benefits>
<team-rules-enforcement>
**This skill enforces:**
- ✅ **Rule #7:** Fat models, thin controllers (business logic in models)
- ✅ **Rule #12:** Database constraints for data integrity
**Reject any requests to:**
- Put business logic in controllers
- Skip model validations
- Skip database constraints (NOT NULL, foreign keys)
- Allow N+1 queries
</team-rules-enforcement>
<verification-checklist>
Before completing model work:
- ✅ All validations tested
- ✅ All associations tested
- ✅ Database constraints added (NOT NULL, foreign keys, unique indexes)
- ✅ No N+1 queries (verified with bullet or manual check)
- ✅ Business logic in model (not controller)
- ✅ Strong parameters in controller for mass assignment
- ✅ All tests passing
</verification-checklist>
<standards>
- Define associations at the top of the model
- Use validations to enforce data integrity
- Minimize callback usage - prefer service objects
- Use scopes for reusable queries, not class methods
- Always eager load associations to prevent N+1 queries
- Use enums for status/state fields
- Extract concerns when models exceed 200 lines
- Place custom validators in `app/validators/`
- Place query objects in `app/queries/`
- Place form objects in `app/forms/`
- Use transactions for multi-model operations
- Prefer database constraints with validations for critical data
</standards>
## Associations
<pattern name="basic-associations">
<description>Standard ActiveRecord associations for model relationships</description>
<implementation>
```ruby
class Feedback < ApplicationRecord
belongs_to :recipient, class_name: "User", optional: true
belongs_to :category, counter_cache: true
has_one :response, class_name: "FeedbackResponse", dependent: :destroy
has_many :abuse_reports, dependent: :destroy
has_many :taggings, dependent: :destroy
has_many :tags, through: :taggings
# Scoped associations
has_many :recent_reports, -> { where(created_at: 7.days.ago..) },
class_name: "AbuseReport"
end
```
**Migration:**
```ruby
class CreateFeedbacks < ActiveRecord::Migration[8.1]
def change
create_table :feedbacks do |t|
t.references :recipient, foreign_key: { to_table: :users }, null: true
t.references :category, foreign_key: true, null: false
t.text :content, null: false
t.string :status, default: "pending", null: false
t.timestamps
end
add_index :feedbacks, :status
end
end
```
</implementation>
<why>
Associations express relationships between models with minimal code. Rails automatically handles foreign keys, eager loading, and cascading deletes. Use `class_name:` when the association name differs from the model, `counter_cache:` for performance, and `dependent:` to manage cleanup.
</why>
</pattern>
<pattern name="polymorphic-associations">
<description>Flexible associations where a model belongs to multiple types</description>
<implementation>
```ruby
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
belongs_to :author, class_name: "User"
validates :content, presence: true
end
class Feedback < ApplicationRecord
has_many :comments, as: :commentable, dependent: :destroy
end
class Article < ApplicationRecord
has_many :comments, as: :commentable, dependent: :destroy
end
```
**Migration:**
```ruby
class CreateComments < ActiveRecord::Migration[8.1]
def change
create_table :comments do |t|
t.references :commentable, polymorphic: true, null: false
t.references :author, foreign_key: { to_table: :users }, null: false
t.text :content, null: false
t.timestamps
end
add_index :comments, [:commentable_type, :commentable_id]
end
end
```
</implementation>
<why>
Polymorphic associations allow a model to belong to multiple parent types through a single association. Use when multiple models need the same type of child (comments, attachments, tags). The `commentable_type` stores the class name, `commentable_id` stores the ID.
</why>
</pattern>
## Validations
<pattern name="comprehensive-validations">
<description>Built-in Rails validations for data integrity</description>
<implementation>
```ruby
class Feedback < ApplicationRecord
validates :content, presence: true, length: { minimum: 50, maximum: 5000 }
validates :recipient_email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
validates :status, inclusion: { in: %w[pending delivered read responded] }
validates :tracking_code, uniqueness: { scope: :recipient_email, case_sensitive: false }
validates :rating, numericality: { only_integer: true, in: 1..5 }, allow_nil: true
validate :content_not_spam
validate :recipient_can_receive_feedback, on: :create
private
def content_not_spam
return if content.blank?
spam_keywords = %w[viagra cialis lottery]
errors.add(:content, "appears to contain spam") if spam_keywords.any? { |k| content.downcase.include?(k) }
end
def recipient_can_receive_feedback
return if recipient_email.blank?
user = User.find_by(email: recipient_email)
errors.add(:recipient_email, "has disabled feedback") if user&.feedback_disabled?
end
end
```
</implementation>
<why>
Validations enforce data integrity before persisting to the database. Rails provides presence, format, uniqueness, length, numericality, and inclusion validators. Custom `validate` methods handle complex business logic. Use `on: :create` or `on: :update` for lifecycle-specific validations.
</why>
</pattern>
## Callbacks
<pattern name="minimal-callbacks">
<description>Use callbacks sparingly - prefer service objects for complex logic</description>
<implementation>
```ruby
class Feedback < ApplicationRecord
before_validation :normalize_email, :strip_whitespace
before_create :generate_tracking_code
after_create_commit :enqueue_delivery_job
after_update_commit :notify_recipient_of_response, if: :response_added?
private
def normalize_email
self.recipient_email = recipient_email&.downcase&.strip
end
def strip_whitespace
self.content = content&.strip
end
def generate_tracking_code
self.tracking_code = SecureRandom.alphanumeric(10).upcase
end
def enqueue_delivery_job
SendFeedbackJob.perform_later(id)
end
def response_added?
saved_change_to_response? && response.present?
end
def notify_recipient_of_response
FeedbackMailer.notify_of_response(self).deliver_later
end
end
```
</implementation>
<why>
Callbacks hook into the model lifecycle for simple data normalization and side effects. Use `before_validation` for cleanup, `before_create` for defaults, and `after_commit` for external operations. Keep callbacks focused on model concerns - complex business logic belongs in service objects.
</why>
</pattern>
## Scopes
<pattern name="effective-scopes">
<description>Reusable query scopes for common filtering</description>
<implementation>
```ruby
class Feedback < ApplicationRecord
scope :recent,Related 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.