Skip to content

Instantly share code, notes, and snippets.

@kaznum
Created May 3, 2011 14:57
Show Gist options
  • Save kaznum/953476 to your computer and use it in GitHub Desktop.
Save kaznum/953476 to your computer and use it in GitHub Desktop.
FIX ME: Sample for metaprogramming: Dynamic and lazy definition of attributes and methods.
class Person
def initialize(args)
args.each do |key, value|
self.class.send(:attr_accessor, :"#{key}") unless instance_variables.include?(:"@#{key}")
instance_variable_set(:"@#{key}", value)
end
end
def self.undef_has_a_var_which_begins_with(var)
method_name = "has_a_#{var}_which_begins_with?"
send("undef_method", method_name) if method_defined? method_name
end
def self.define_has_a_var_which_begins_with(var)
method_name = "has_a_#{var}_which_begins_with?"
define_method(method_name) do |expectation|
value = instance_variable_get(:"@#{var}")
if value.is_a?(String)
value.split(//)[0].downcase == expectation.downcase
else
self.class.undef_has_a_var_which_begins_with(var)
method_missing(method_name.to_sym)
end
end
end
def method_missing(m, *args, &block)
if m.to_s =~ /has_(a|the)_(.+)_(which|that)_begins_with\?/ &&
instance_variables.include?(:"@#{Regexp.last_match[2]}") &&
instance_variable_get(:"@#{Regexp.last_match[2]}").is_a?(String)
var_name = Regexp.last_match[2]
self.class.define_has_a_var_which_begins_with(var_name)
send("has_a_#{var_name}_which_begins_with\?".to_sym, *args, &block)
else
super(m, *args, &block)
end
end
end
#### sample #####
if RUBY_VERSION < "1.9"
raise "This script can be executed only on Ruby 1.9. Sorry."
end
shimada = Person.new(:name => "Shimada", :age => 18, :sex => :half, :fuga => "bababa")
p shimada.has_a_name_which_begins_with?("S") ? "Good" : "Suck"
p shimada.has_the_name_which_begins_with?("S") ? "Good" : "Suck"
shimada.name = 5
# the following raises Error because name isn't a String
p shimada.has_the_name_which_begins_with?("5") ? "Good" : "Suck"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment