Skip to content

Instantly share code, notes, and snippets.

@capnslipp
Created February 20, 2012 00:51
Show Gist options
  • Save capnslipp/1866858 to your computer and use it in GitHub Desktop.
Save capnslipp/1866858 to your computer and use it in GitHub Desktop.
Stack Overflow Question #5390537 (http://stackoverflow.com/questions/5390537)
## encoding: utf-8
## Alex D's solution (1st revision) to http://stackoverflow.com/questions/5390537/best-practices-and-implementation-for-macro-and-class-level-accessor-methods/9019388#9019388
module MacroMethods
private
def full_name(full_name)
# non-trivial, one-time-only set-up code exists here in actual usage
self.class_eval { const_set :FULL_NAME, full_name.to_s }
# this method can only be called once in the definition of any given class,
# because after the first call, it will be redefined!
extend AccessorMethods
end
end
module AccessorMethods
public
def full_name
# a non-trivial, runtime-calculated value is returned here in actual usage
self::FULL_NAME.upcase
end
end
class Base
extend MacroMethods
end
class Something < Base
full_name 'after this call, I will get a new full_name method!'
end
class SomethingElse < Base
full_name 'so will I!'
end
puts "Something.full_name: #{Something.full_name}"
puts "SomethingElse.full_name: #{SomethingElse.full_name}"
## encoding: utf-8
## Alex D's solution (2nd revision) to http://stackoverflow.com/questions/5390537/best-practices-and-implementation-for-macro-and-class-level-accessor-methods/9019388#9019388
module MacroMethods
private
def full_name(full_name)
# non-trivial, one-time-only set-up code exists here in actual usage
self.class_eval { const_set :FULL_NAME, full_name.to_s }
# this method can only be called once in the definition of any given class,
# because after the first call, it will be redefined!
define_method(:full_name) do
# a non-trivial, runtime-calculated value is returned here in actual usage
self.class.class_eval { self::FULL_NAME.upcase }
end
end
end
class Base
extend MacroMethods
end
class Something < Base
full_name 'after this call, I will get a new full_name method!'
end
class SomethingElse < Base
full_name 'so will I!'
end
puts "Something.new.full_name: #{Something.new.full_name}"
puts "SomethingElse.new.full_name: #{SomethingElse.new.full_name}"
## encoding: utf-8
## Modification of Alex D's solution to http://stackoverflow.com/questions/5390537/best-practices-and-implementation-for-macro-and-class-level-accessor-methods/9019388#9019388
module MacroMethods
private
def full_name(full_name)
# non-trivial, one-time-only set-up code exists here in actual usage
self.class_eval { const_set :FULL_NAME, full_name.to_s }
# this method can only be called once in the definition of any given class,
# because after the first call, it will be redefined!
self.singleton_class.instance_eval {
undef_method(:full_name)
define_method(:full_name) do
# a non-trivial, runtime-calculated value is returned here in actual usage
self::FULL_NAME.upcase
end
public :full_name
}
define_method(:full_name) do
# a non-trivial, runtime-calculated value is returned here in actual usage
self.class.class_eval { self::FULL_NAME.upcase }
end
end
end
class Base
extend MacroMethods
end
class Something < Base
full_name 'after this call, I will get a new full_name method!'
end
class SomethingElse < Base
full_name 'so will I!'
end
puts "Something.new.full_name: #{Something.new.full_name}"
puts "SomethingElse.new.full_name: #{SomethingElse.new.full_name}"
puts "Something.full_name: #{Something.full_name}"
puts "SomethingElse.full_name: #{SomethingElse.full_name}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment