From: "Jesús Gabriel y Galán" Date: 2008-05-08T01:16:21+09:00 Subject: Re: Reading from file, create a class with variables On Tue, May 6, 2008 at 11:33 AM, Pelle Strul wrote: > Hi, I'm trying to load a file with specifications like: > > title :Person > attribute :name, String > attribute :age, Fixnum > constraint :name, 'name != nil' > constraint :name, 'name.size > 0' > constraint :name, 'name =~ /^[A-Z]/' > constraint :age, 'age >= 0' > > After which I want to create a class Person, with variables name being a > string, variable age being a fixed number and also the constraints for > them. > Any ideas how these specifications can be read and declared? This is my first try at solving this problem. It might not be very good, and I would also like people's comments on my solution, since I would like to learn how to do these things better: class ClassGenerator def initialize @constraints = {} @attr_names = [] end def title the_title @class_name = the_title end def attribute attr, klazz @attr_names << attr # First constraint is to check the class @constraints[attr] = ["#{attr}.is_a? #{klazz}"] end def constraint attr, constr @constraints[attr] << constr end def generate data instance_eval data klazz = Class.new klazz.class_eval "attr_reader #{@attr_names.map{|k| ":#{k}"}.join(",")}" init_params = @attr_names.join(",") initialize_body = "" @attr_names.each do |attr| @constraints[attr].each do |constraint| initialize_body << "raise ArgumentError.new('#{constraint}') unless #{constraint};" end initialize_body << "@#{attr}=#{attr};" end klazz.class_eval "def initialize(#{init_params}); #{initialize_body}; end" Object.const_set @class_name, klazz end end # The data could be read from a file, obviously data =< 0' constraint :name, 'name =~ /^[A-Z]/' constraint :age, 'age >= 0' EOD # This should create a Person class, with # an initialize method with a param for each attribute # which checks the constraints raising ArgumentError # if not passed, and assigning to an instance variable # It also creates attr_readers for the attributes. ClassGenerator.new.generate data # So now we can do: a = Person.new "A", 3 puts a.name puts a.age # These should fail with ArgumentError # The msg of the error contains the constraint Person.new "A", -3 Person.new "a", 3 Person.new '', 3 Hope this helps and I would appreciate any comment on my code. Jesus.