andrew-kane-gem-writer

star 0

当按照 Andrew Kane 经过验证的模式和哲学编写 Ruby gems 时,应使用此技能。它适用于创建新的 Ruby gems、重构现有 gems、设计 gem API,或需要简洁、最小、生产就绪的 Ruby 库代码时。在请求如"创建 gem"、"编写 Ruby 库"、"设计 gem API"或提及 Andrew Kane 风格时触发。

Hff1230 By Hff1230 schedule Updated 2/28/2026

name: andrew-kane-gem-writer description: 当按照 Andrew Kane 经过验证的模式和哲学编写 Ruby gems 时,应使用此技能。它适用于创建新的 Ruby gems、重构现有 gems、设计 gem API,或需要简洁、最小、生产就绪的 Ruby 库代码时。在请求如"创建 gem"、"编写 Ruby 库"、"设计 gem API"或提及 Andrew Kane 风格时触发。

Andrew Kane Gem Writer

按照 Andrew Kane 来自 100+ gems、374M+ 下载量的经过验证的模式编写 Ruby gems(Searchkick、PgHero、Chartkick、Strong Migrations、Lockbox、Ahoy、Blazer、Groupdate、Neighbor、Blind Index)。

核心哲学

简洁胜过巧妙。 零依赖或最小依赖。显式代码优于元编程。Rails 集成而不依赖 Rails。每个模式都服务于生产用例。

入口点结构

每个 gem 在 lib/gemname.rb 中都遵循这种精确模式:

# 1. 依赖(优先使用标准库)
require "forwardable"

# 2. 内部模块
require_relative "gemname/model"
require_relative "gemname/version"

# 3. 条件 Rails(关键 - 永远不要直接 require Rails)
require_relative "gemname/railtie" if defined?(Rails)

# 4. 带有配置和错误的模块
module GemName
  class Error < StandardError; end
  class InvalidConfigError < Error; end

  class << self
    attr_accessor :timeout, :logger
    attr_writer :client
  end

  self.timeout = 10  # 立即设置默认值
end

类宏 DSL 模式

Kane 模式的签名——单次方法调用配置一切:

# 用法
class Product < ApplicationRecord
  searchkick word_start: [:name]
end

# 实现
module GemName
  module Model
    def gemname(**options)
      unknown = options.keys - KNOWN_KEYWORDS
      raise ArgumentError, "unknown keywords: #{unknown.join(", ")}" if unknown.any?

      mod = Module.new
      mod.module_eval do
        define_method :some_method do
          # 实现
        end unless method_defined?(:some_method)
      end
      include mod

      class_eval do
        cattr_reader :gemname_options, instance_reader: false
        class_variable_set :@@gemname_options, options.dup
      end
    end
  end
end

Rails 集成

始终使用 ActiveSupport.on_load——永远不要直接 require Rails gems:

# 错误
require "active_record"
ActiveRecord::Base.include(MyGem::Model)

# 正确
ActiveSupport.on_load(:active_record) do
  extend GemName::Model
end

# 使用 prepend 进行行为修改
ActiveSupport.on_load(:active_record) do
  ActiveRecord::Migration.prepend(GemName::Migration)
end

配置模式

使用 class << selfattr_accessor,而不是配置对象:

module GemName
  class << self
    attr_accessor :timeout, :logger
    attr_writer :master_key
  end

  def self.master_key
    @master_key ||= ENV["GEMNAME_MASTER_KEY"]
  end

  self.timeout = 10
  self.logger = nil
end

错误处理

简单的层次结构和信息性消息:

module GemName
  class Error < StandardError; end
  class ConfigError < Error; end
  class ValidationError < Error; end
end

# 尽早验证,使用 ArgumentError
def initialize(key:)
  raise ArgumentError, "Key must be 32 bytes" unless key&.bytesize == 32
end

测试(仅 Minitest)

# test/test_helper.rb
require "bundler/setup"
Bundler.require(:default)
require "minitest/autorun"
require "minitest/pride"

# test/model_test.rb
class ModelTest < Minitest::Test
  def test_basic_functionality
    assert_equal expected, actual
  end
end

反模式避免

  • method_missing(改用 define_method
  • 配置对象(使用类访问器)
  • @@class_variables(使用 class << self
  • 直接 require Rails gems
  • 许多运行时依赖
  • 在 gems 中提交 Gemfile.lock
  • RSpec(使用 Minitest)
  • 重的 DSL(首选显式 Ruby)

参考文件

有关更深入的模式,请参阅:

Install via CLI
npx skills add https://github.com/Hff1230/FFNotes --skill andrew-kane-gem-writer
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator