Skip to content

Instantly share code, notes, and snippets.

@panzi
Last active December 24, 2015 16:39
Show Gist options
  • Save panzi/6830055 to your computer and use it in GitHub Desktop.
Save panzi/6830055 to your computer and use it in GitHub Desktop.
Very similar class to OpenStruct, except all instances are immutable. Use ConstStruct.derive("MyClass") to dynamically create a subclass (so instance.inspect gives a nicer/more specific class name).
class ConstStruct
def self.derive(name)
cls = Class.new(ConstStruct)
cls.instance_variable_set :@name, name
def cls.name; @name end
def cls.inspect; @name end
def cls.to_s; @name end
cls
end
def initialize(attrs)
for key, val in attrs
raise SyntaxError, "illegal method name: #{key}" unless /^[a-z_][a-zA-Z_0-9]*$/ === key
instance_variable_set :"@#{key}", val
instance_eval "def #{key}; @#{key} end"
if TrueClass === val or FalseClass === val
instance_eval "def #{key}?; @#{key} end"
end
end
end
def [](name)
instance_variable_get(:"@#{name}")
end
InspectKey = :__inspect_key__ # :nodoc:
def inspect
return "<#{self.class}>" if instance_variables.empty?
str = "<#{self.class} "
ids = (Thread.current[InspectKey] ||= [])
if ids.include?(object_id)
return str << '...>'
end
ids << object_id
begin
str << instance_variables.map {|var|
"#{var}=#{instance_variable_get(var).inspect}"
}.join(", ")
return str << '>'
ensure
ids.pop
end
end
alias :to_s :inspect
def to_hash
hash = {}
for var in instance_variables
svar = var.to_s
hash[svar.slice(1,svar.length-1).to_sym] = instance_variable_get(var)
end
hash
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment