Skip to content
Browse files

remove inheritance, back to metaprogramming. inheritance was too frag…

…ile if derived class redefines self.keys
  • Loading branch information...
1 parent 2afb22a commit c2bb4aeed3d693854c6a2ce34042e45588ac961e @ronen committed May 15, 2012
Showing with 35 additions and 42 deletions.
  1. +35 −42 lib/key_struct/key_struct.rb
View
77 lib/key_struct/key_struct.rb
@@ -14,47 +14,6 @@ def self.accessor(*keys)
private
- class Base
- include Comparable
-
- def initialize(args={})
- args = self.class.defaults.merge(args)
- self.class.keys.each do |key|
- instance_variable_set("@#{key}".to_sym, args.delete(key))
- end
- raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')} -- KeyStruct accepts #{self.class.keys.map(&:inspect).join(' ')}" if args.any?
- end
-
- def ==(other)
- self.class.keys.all?{|key| other.respond_to?(key) and self.send(key) == other.send(key)}
- end
-
- def <=>(other)
- self.class.keys.each do |key|
- cmp = (self.send(key) <=> other.send(key))
- return cmp unless cmp == 0
- end
- 0
- end
-
- def to_hash
- Hash[*self.class.keys.map{ |key| [key, self.send(key)]}.flatten(1)]
- end
-
- def to_s
- "[#{self.class.display_name} #{self.class.keys.map{|key| "#{key}:#{self.send(key)}"}.join(' ')}]"
- end
-
- def inspect
- "<#{self.class.display_name}:0x#{self.object_id.to_s(16)} #{self.class.keys.map{|key| "#{key}:#{self.send(key).inspect}"}.join(' ')}>"
- end
-
- def self.display_name
- self.name || "KeyStruct.#{access}"
- end
- end
-
-
# for anonymous superclasses, such as
#
# class Foo < KeyStruct[:a, :b]
@@ -86,12 +45,46 @@ def self.define_key_struct(access, keys)
defaults = (Hash === keys.last) ? keys.pop.dup : {}
keys += defaults.keys
- Class.new(Base).tap{ |klass|
+ Class.new.tap{ |klass|
klass.class_eval do
+ include Comparable
+
send "attr_#{access}", *keys
+
define_singleton_method(:keys) { keys }
define_singleton_method(:defaults) { defaults }
define_singleton_method(:access) { access }
+ define_singleton_method(:display_name) { self.name || "KeyStruct.#{access}" }
+
+ define_method(:initialize) do | args={} |
+ args = defaults.merge(args)
+ keys.each do |key|
+ instance_variable_set("@#{key}".to_sym, args.delete(key))
+ end
+ raise ArgumentError, "Invalid argument(s): #{args.keys.map(&:inspect).join(' ')} -- KeyStruct accepts #{keys.map(&:inspect).join(' ')}" if args.any?
+ end
+
+ define_method(:to_s) {
+ "[#{self.class.display_name} #{keys.map{|key| "#{key}:#{self.send(key)}"}.join(' ')}]"
+ }
+ define_method(:inspect) {
+ "<#{self.class.display_name}:0x#{self.object_id.to_s(16)} #{keys.map{|key| "#{key}:#{self.send(key).inspect}"}.join(' ')}>"
+ }
+ define_method(:to_hash) {
+ Hash[*keys.map{ |key| [key, self.send(key)]}.flatten(1)]
+ }
+ define_method(:==) { |other|
+ self.class.keys.all?{|key| other.respond_to?(key) and self.send(key) == other.send(key)}
+ }
+
+ define_method(:<=>) { |other|
+ keys.each do |key|
+ cmp = (self.send(key) <=> other.send(key))
+ return cmp unless cmp == 0
+ end
+ 0
+ }
+
end
}
end

0 comments on commit c2bb4ae

Please sign in to comment.
Something went wrong with that request. Please try again.