Method 1: class_eval with string
class Class
def _attr_reader *vars
vars.each do |var|
class_eval <<-COD
def self.#{var}
@@#{var}
end
COD
end
end
end
Method 2: define_method and class_variable_get
class Class
def _attr_reader *vars
vars.each do |var|
self.class.send(:define_method, var) do
class_variable_get "@@#{var}"
end
end
end
end
Testing:
class Test
@@foo = 'hihaha'
@@bar = 'eita'
_attr_reader :foo, :bar
end
puts Test.foo #=> hihaha
puts Test.bar #=> eita
I prefer the second way because I tend to avoid "evals", due to performance issues of parsing strings. You could use class_eval with a block instead of string, but it's method 2 with more code:
Method 3: class_eval with a block
class Class
def _attr_reader *vars
vars.each do |var|
class_eval do
self.class.send(:define_method, var) do
class_variable_get "@@#{var}"
end
end
end
end
end
Method 4: instance_eval:
class Class
def _attr_reader *vars
vars.each do |var|
(class << self; self; end).instance_eval do
define_method(var) do
class_variable_get "@@#{var}"
end
end
end
end
end