Skip to content

Instantly share code, notes, and snippets.

@krisleech
Last active February 1, 2017 10:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krisleech/593a58691519b45b07ad7c6ebcc3a3bc to your computer and use it in GitHub Desktop.
Save krisleech/593a58691519b45b07ad7c6ebcc3a3bc to your computer and use it in GitHub Desktop.
Ruby object/class meta data
module Meta
  def meta
    @meta ||= {}
  end
end

[String Hash Array].each { |klass| klass.include(Meta) }
  
name = "Kris"
name.meta[:tained] = false
name.meta[:tained] # => false

Meta data does not influence the value of an object, i.e. equality.

name == "Kris" # => true

The classes themseleves can also have meta data:

class Foo
  extend Meta
end

Foo.meta[:doc] = "Provides XYZ"

This can also be DSL'd:

module DocString
  def self.included(base)
    base.include(Meta)
    base.extend(ClassMethods)
  end
  
  module ClassMethods
    def doc(text = nil)
      if text
        meta[:doc] = text
      else
        meta[:doc] || ""
      end
    end
  end
end

class Foo
  include DocString
  
  doc "Provides XYZ"
end

Foo.doc # => "Provides XYZ"

Now we have docs inside out REPL.

Notes

It does not work with Integer or Symbol instances since they are frozen.

Some other examples:

module AutoTag
   def self.included(base)
     base.include(Meta)
   end
   
  def initialize(*)
    meta[:created_at] = Time.now
    meta[:source_file] = __FILE__
    meta[:source_line] = __LINE__
    super
  end
end

class Bar
  include AutoTag
end

bar = Bar.new
bar.meta[:created_at] # => Time
bar.meta[:source_file] #=> "(irb)"
bar.meta[:source_line] # => 81

You could imagine taking this further and being able to print the source code for an object. Something like show-source in Pry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment