andrew-kane-gem-writer

This skill should be used when writing Ruby gems following Andrew Kane's proven patterns and philosophy. It applies when creating new Ruby gems, refactoring…

INSTALLATION
npx skills add https://github.com/everyinc/compound-engineering-plugin --skill andrew-kane-gem-writer
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

3. Conditional Rails (CRITICAL - never require Rails directly)

require_relative "gemname/railtie" if defined?(Rails)

4. Module with config and errors

module GemName

class Error < StandardError; end

class InvalidConfigError < Error; end

class << self

attr_accessor :timeout, :logger

attr_writer :client

end

self.timeout = 10 # Defaults set immediately

end

## Class Macro DSL Pattern

The signature Kane pattern—single method call configures everything:

Usage

class Product < ApplicationRecord

searchkick word_start: [:name]

end

Implementation

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

# implementation

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 Integration

**Always use `ActiveSupport.on_load`—never require Rails gems directly:**

WRONG

require "active_record"

ActiveRecord::Base.include(MyGem::Model)

CORRECT

ActiveSupport.on_load(:active_record) do

extend GemName::Model

end

Use prepend for behavior modification

ActiveSupport.on_load(:active_record) do

ActiveRecord::Migration.prepend(GemName::Migration)

end


## Configuration Pattern

Use `class << self` with `attr_accessor`, not Configuration objects:

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


## Error Handling

Simple hierarchy with informative messages:

module GemName

class Error < StandardError; end

class ConfigError < Error; end

class ValidationError < Error; end

end

Validate early with ArgumentError

def initialize(key:)

raise ArgumentError, "Key must be 32 bytes" unless key&#x26;.bytesize == 32

end


## Testing (Minitest Only)

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


## Gemspec Pattern

Zero runtime dependencies when possible:

Gem::Specification.new do |spec|

spec.name = "gemname"

spec.version = GemName::VERSION

spec.required_ruby_version = ">= 3.1"

spec.files = Dir[".{md,txt}", "{lib}//"]

spec.require_path = "lib"

# NO add_dependency lines - dev deps go in Gemfile

end

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card