Skip to content

Instantly share code, notes, and snippets.

@isaacsanders
Created August 10, 2012 17:16
Show Gist options
  • Save isaacsanders/3315843 to your computer and use it in GitHub Desktop.
Save isaacsanders/3315843 to your computer and use it in GitHub Desktop.
Do you prefer metaprogramming, or lots of repetition?
require 'chemistry/temperature'
module Chemistry
class Element
class << self
def property(name, type, &transformer)
define_property_setter name, type, &transformer
define_property_getter name
end
def define_property_setter name, type, &transformer
define_class_method name do |value|
value = transformer.call value if block_given?
if value.is_a? type
const_set name.to_s.upcase, value
else
raise TypeError, "can't convert #{value.class} into #{type}"
end
end
end
def define_class_method name, &definition
class_methods = Module.new
class_methods.instance_eval do
define_method name, &definition
end
extend class_methods
end
def define_property_getter name
define_method name do
self.class.const_get name.to_s.upcase
end
end
def temperature_property(name)
property name, Chemistry::Temperature::Unit do |value|
Chemistry::Temperature.parse value
end
end
end
property :symbol, String
property :atomic_number, Integer
property :atomic_weight, Numeric
temperature_property :melting_point
temperature_property :boiling_point
end
end
module Chemistry
class Element
class << self
def symbol symbol
if symbol.is_a? String
const_set :SYMBOL, symbol
else
raise TypeError, "can't convert #{symbol.class} into String"
end
end
def atomic_number atomic_number
if atomic_number.is_a? Integer
const_set :ATOMIC_NUMBER, atomic_number
else
raise TypeError, "can't convert #{atomic_number.class} into Integer"
end
end
def atomic_weight atomic_weight
if atomic_weight.is_a? Numeric
const_set :ATOMIC_WEIGHT, atomic_weight
else
raise TypeError, "can't convert #{atomic_weight.class} into Numeric"
end
end
end
def symbol
self.class::SYMBOL
end
def atomic_number
self.class::ATOMIC_NUMBER
end
def atomic_weight
self.class::ATOMIC_WEIGHT
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment