Eigenclasses (metaclasses) in Ruby
Ruby
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
.rspec
.travis.yml
Gemfile
Gemfile.lock
LICENSE
README.md
eigenclass.gemspec

README.md

Sean Huber eigenclass

Build Status Code Climate Coverage Gem Version

Eigenclasses aka metaclasses or singleton classes in Ruby.

Check out the metaclass implementations in other languages for more examples.

Note: This gem was originally written back in 2008. Since then, Ruby has introduced a couple new methods which provide the same functionality as this gem's eigenclass and edefine_method methods.

Installation

gem install eigenclass

Requirements

Ruby 1.8.7+

Usage

Everything in Ruby is an object, including classes.

SomeObject = Class.new

Every object has an eigenclass.

SomeObject.eigenclass #=> #<Class:#<SomeObject:0x007f9611030300>>

The implementation of the eigenclass method is pretty simple.

class Object
  def eigenclass
    class << self
      self
    end
  end
end

Evaluating code within an eigenclass lets us do some cool things like defining class level attributes.

SomeObject.eigenclass_eval do
  attr_accessor :example
end

SomeObject.example = :test
SomeObject.example #=> :test

The convenience methods for defining class level methods makes this even easier.

class SomeObject
  eattr_accessor :example_accessor
  eattr_reader :example_reader
  eattr_writer :example_writer

  ealias_method :new_example_accessor, :example_accessor

  edefine_method(:example_class_method) do
    1 + 1
  end
end

SomeObject.example_class_method #=> 2

When we extend modules, we're actually just calling include on an object's eigenclass.

SomeObject.eigenclass.included_modules #=> [Eigenclass, Kernel]

Example = Module.new
SomeObject.extend(Example)

SomeObject.eigenclass.included_modules #=> [Example, Eigenclass, Kernel]

A convenience method for viewing an object's extended modules is available for us as well.

SomeObject.extended_modules #=> [Example, Eigenclass, Kernel]

Since all objects have an eigenclass, we can even define methods for a single instance of a class.

object = SomeObject.new
object.eattr_accessor :example
object.example = :test
object.example #=> :test

other_object = SomeObject.new
other_object.example #=> NoMethodError undefined method `example' for #<SomeObject:0x007fee348dde00>

This is pretty incredible! We can hook in and inject behavior into any and all objects - at runtime!

Ruby is like one big plugin framework - with an awesome standard library and amazing community!

API

YARD Documentation

All methods defined by this gem are simple delegators to existing methods on the eigenclass object. The links below redirect to each corresponding method in the standard library documentation.

Testing

bundle exec rspec

Contributing

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

License

MIT - Copyright © 2008 Sean Huber