Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计异常

rails-active-record-patternsRails active record 模式

Agent Skill

rails-active-record-patterns 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

776

周安装

33

GitHub Stars

142

下载量

272
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:rails-active-record-patterns(Rails active record 模式)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/rails-active-record-patterns
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill rails-active-record-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill rails-active-record-patterns

简介

用于检索 Rails 中 Active Record 的数据建模与查询优化方案。

  • 适合在数据库设计或性能调优时寻找典型用法与反模式。
  • 通过 GitHub 安装,支持按关键词搜索相关代码片段或指南。
  • 应避免直接复制未经测试的查询语句,尤其涉及关联与事务时。
  • 推荐结合 EXPLAIN 分析慢查询,确保执行效率。

SKILL.md

Rails Active Record Patterns

Master Active Record patterns for building robust Rails models with proper associations, validations, scopes, and query optimization.

Overview

Active Record is Rails' Object-Relational Mapping (ORM) layer that connects model classes to database tables. It implements the Active Record pattern, where each object instance represents a row in the database and includes both data and behavior.

Installation and Setup

Creating Models

# Generate a model with migrations
rails generate model User name:string email:string:uniq

# Generate model with associations
rails generate model Post title:string body:text user:references

# Run migrations
rails db:migrate

Database Configuration

# config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>

Core Patterns

1. Basic Model Definition

# app/models/user.rb
class User < ApplicationRecord
  # Validations
  validates :email, presence: true, uniqueness: true,
    format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :name, presence: true, length: { minimum: 2, maximum: 50 }

  # Callbacks
  before_save :normalize_email
  after_create :send_welcome_email

  # Scopes
  scope :active, -> { where(active: true) }
  scope :recent, -> { order(created_at: :desc).limit(10) }

  private

  def normalize_email
    self.email = email.downcase.strip
  end

  def send_welcome_email
    UserMailer.welcome(self).deliver_later
  end
end

2. Associations

# app/models/user.rb
class User < ApplicationRecord
  # One-to-many
  has_many :posts, dependent: :destroy
  has_many :comments, dependent: :destroy

  # Many-to-many through join table
  has_many :memberships, dependent: :destroy
  has_many :organizations, through: :memberships

  # Has-one
  has_one :profile, dependent: :destroy

  # Polymorphic association
  has_many :images, as: :imageable, dependent: :destroy
end

# app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy
  has_many :commenters, through: :comments, source: :user

  # Counter cache
  belongs_to :user, counter_cache: true
end

# app/models/organization.rb
class Organization < ApplicationRecord
  has_many :memberships, dependent: :destroy
  has_many :users, through: :memberships
end

# app/models/membership.rb
class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :organization

  enum role: { member: 0, admin: 1, owner: 2 }
end

3. Advanced Queries

# app/models/post.rb
class Post < ApplicationRecord
  # Scopes with arguments
  scope :by_author, ->(user_id) { where(user_id: user_id) }
  scope :published_after, ->(date) { where('published_at > ?', date) }
  scope :with_tag, ->(tag) { joins(:tags).where(tags: { name: tag }) }

  # Class methods for complex queries
  def self.popular(threshold = 100)
    where('views_count >= ?', threshold)
      .order(views_count: :desc)
  end

  def self.search(query)
    where('title ILIKE ? OR body ILIKE ?', "%#{query}%", "%#{query}%")
  end

  # Query with joins and includes
  def self.with_user_and_comments
    includes(:user, comments: :user)
      .order(created_at: :desc)
  end
end

# Usage
Post.published_after(1.week.ago)
  .by_author(current_user.id)
  .with_tag('rails')
  .popular(50)

4. Validations

# app/models/user.rb
class User < ApplicationRecord
  # Presence validation
  validates :email, :name, presence: true

  # Uniqueness validation
  validates :email, uniqueness: { case_sensitive: false }

  # Format validation
  validates :username, format: {
    with: /\A[a-z0-9_]+\z/,
    message: "only allows lowercase letters, numbers, and underscores"
  }

  # Length validation
  validates :bio, length: { maximum: 500 }
  validates :password, length: { minimum: 8 }, if: :password_required?

  # Numericality validation
  validates :age, numericality: {
    only_integer: true,
    greater_than_or_equal_to: 18,
    less_than: 120
  }

  # Custom validation
  validate :email_domain_allowed

  private

  def email_domain_allowed
    return if email.blank?

    domain = email.split('@').last
    unless ALLOWED_DOMAINS.include?(domain)
      errors.add(:email, "domain #{domain} is not allowed")
    end
  end

  def password_required?
    new_record? || password.present?
  end
end

5. Callbacks

# app/models/post.rb
class Post < ApplicationRecord
  # Before callbacks
  before_validation :normalize_title
  before_save :calculate_reading_time
  before_create :generate_slug

  # After callbacks
  after_create :notify_followers
  after_update :clear_cache, if: :saved_change_to_body?
  after_destroy :cleanup_attachments

  # Around callbacks
  around_save :log_save_time

  private

  def normalize_title
    self.title = title.strip.titleize if title.present?
  end

  def calculate_reading_time
    return unless body_changed?
    words = body.split.size
    self.reading_time = (words / 200.0).ceil
  end

  def generate_slug
    self.slug = title.parameterize
  end

  def notify_followers
    NotifyFollowersJob.perform_later(self)
  end

  def clear_cache
    Rails.cache.delete("post/#{id}")
  end

  def cleanup_attachments
    attachments.purge_later
  end

  def log_save_time
    start = Time.current
    yield
    duration = Time.current - start
    Rails.logger.info "Post #{id} saved in #{duration}s"
  end
end

6. Enum Patterns

# app/models/post.rb
class Post < ApplicationRecord
  # Basic enum
  enum status: {
    draft: 0,
    published: 1,
    archived: 2
  }

  # Enum with prefix/suffix
  enum visibility: {
    public: 0,
    private: 1,
    unlisted: 2
  }, _prefix: :visibility

  # Multiple enums
  enum content_type: {
    article: 0,
    video: 1,
    podcast: 2
  }, _suffix: :content

  # Scopes automatically created
  # Post.draft, Post.published, Post.archived
  # Post.visibility_public, Post.visibility_private
  # Post.article_content, Post.video_content

  # Query methods
  # post.draft?, post.published?, post.archived?
  # post.visibility_public?, post.visibility_private?

  # State transitions
  def publish!
    published! if draft?
  end
end

7. Query Optimization

# app/models/post.rb
class Post < ApplicationRecord
  # Eager loading to avoid N+1
  scope :with_associations, -> {
    includes(:user, :tags, comments: :user)
  }

  # Select specific columns
  scope :title_and_author, -> {
    select('posts.id, posts.title, users.name as author_name')
      .joins(:user)
  }

  # Batch processing
  def self.process_in_batches
    find_each(batch_size: 1000) do |post|
      post.process
    end
  end

  # Pluck for arrays
  def self.recent_titles
    order(created_at: :desc)
      .limit(10)
      .pluck(:title)
  end

  # Exists check (efficient)
  def self.has_recent_posts?(user_id)
    where(user_id: user_id)
      .where('created_at > ?', 1.day.ago)
      .exists?
  end

  # Count with joins
  def self.popular_authors
    joins(:user)
      .group('users.id', 'users.name')
      .select('users.id, users.name, COUNT(posts.id) as posts_count')
      .having('COUNT(posts.id) >= ?', 10)
      .order('posts_count DESC')
  end
end

8. Transactions

# app/services/post_publisher.rb
class PostPublisher
  def self.publish(post, user)
    ActiveRecord::Base.transaction do
      post.update!(status: :published, published_at: Time.current)
      user.increment!(:posts_count)
      NotificationService.notify_followers(post)

      # If any operation fails, entire transaction is rolled back
    end
  rescue ActiveRecord::RecordInvalid => e
    Rails.logger.error "Failed to publish post: #{e.message}"
    false
  end

  # Nested transactions with savepoints
  def self.complex_operation(post)
    ActiveRecord::Base.transaction do
      post.update!(featured: true)

      ActiveRecord::Base.transaction(requires_new: true) do
        # This creates a savepoint
        post.tags.create!(name: 'featured')
      end
    end
  end
end

9. STI (Single Table Inheritance)

# app/models/vehicle.rb
class Vehicle < ApplicationRecord
  validates :make, :model, presence: true

  def max_speed
    raise NotImplementedError
  end
end

# app/models/car.rb
class Car < Vehicle
  validates :doors, presence: true

  def max_speed
    120
  end
end

# app/models/motorcycle.rb
class Motorcycle < Vehicle
  validates :engine_size, presence: true

  def max_speed
    180
  end
end

# Usage
car = Car.create(make: 'Toyota', model: 'Camry', doors: 4)
car.type # => "Car"
Vehicle.all # Returns both cars and motorcycles
Car.all # Returns only cars

10. Concerns

# app/models/concerns/sluggable.rb
module Sluggable
  extend ActiveSupport::Concern

  included do
    before_validation :generate_slug
    validates :slug, presence: true, uniqueness: true
  end

  class_methods do
    def find_by_slug(slug)
      find_by(slug: slug)
    end
  end

  private

  def generate_slug
    return if slug.present?
    base_slug = title.parameterize
    self.slug = unique_slug(base_slug)
  end

  def unique_slug(base_slug)
    slug_candidate = base_slug
    counter = 1

    while self.class.exists?(slug: slug_candidate)
      slug_candidate = "#{base_slug}-#{counter}"
      counter += 1
    end

    slug_candidate
  end
end

# app/models/post.rb
class Post < ApplicationRecord
  include Sluggable
end

Best Practices

  1. Use scopes for reusable queries - Keep query logic in the model
  2. Eager load associations - Prevent N+1 queries with includes/preload
  3. Add database indexes - Index foreign keys and frequently queried columns
  4. Use counter caches - Optimize count queries for associations
  5. Validate at model level - Ensure data integrity with validations
  6. Keep callbacks simple - Extract complex logic to service objects
  7. Use transactions - Ensure data consistency for multi-step operations
  8. Leverage concerns - Share common behavior across models
  9. Use enums for state - Type-safe state management with enums
  10. Write efficient queries - Use select, pluck, and exists appropriately

Common Pitfalls

  1. N+1 queries - Forgetting to eager load associations
  2. Callback hell - Too many callbacks making flow hard to follow
  3. Fat models - Putting too much business logic in models
  4. Missing indexes - Slow queries due to unindexed columns
  5. Unsafe updates - Not using transactions for related operations
  6. Validation bypass - Using update_attribute or save(validate: false)
  7. Memory bloat - Loading all records instead of batching
  8. SQL injection - Using string interpolation in where clauses
  9. Counter cache mismatches - Manual updates breaking counter caches
  10. Ignoring database constraints - Not adding DB-level validations

When to Use

  • Building data-backed Rails applications
  • Implementing business logic tied to database models
  • Creating REST APIs with Rails
  • Developing CRUD interfaces
  • Managing complex data relationships
  • Building multi-tenant applications
  • Creating admin interfaces with Active Admin
  • Implementing soft deletes and audit trails
  • Building reporting and analytics features
  • Creating content management systems

Resources

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

29.39%
按下载量换算80

Claude Code

21.08%
按下载量换算57

OpenCode

20.3%
按下载量换算55

Gemini CLI

13.24%
按下载量换算36

Cursor

8.93%
按下载量换算24

windsurf

3.5%
按下载量换算10

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills