Dynamically adding validations to model instances

Hi,

I have code which generates a definition of a survey / questionnaire
using a few related AR tables. The code I need help with is the code
which converts the survey definition into an object I can pass to the
view to generate the survey form for the user to fill in.

I have a non-AR object called SurveyData. It extends ValidatingBase,
which is described here: Peak Obsession
HowToUseValidationsWithoutExtendingActiveRecord
basically it lets you use ActiveRecord::Validations on a non-AR object.

What I want to do is dynamically read the questions that the survey
needs to ask, and for each one, do the equivalent of:

class SurveyData
attr_accessor fieldname
validates_presence_of fieldname
end

I’ve tried all sorts of things. This is my current non-working version:

class SurveyData < ValidatingBase
include Reloadable

def add_required_fields(field_names)
[field_names].flatten.each { |name|
src=<<-END
attr_accessor :#{name}
validates_presence_of :#{name}
END

   self.class.class_eval src, __FILE__, __LINE__
 }

end
end

It appears to work, but my unit test fails because the
validates_presence_of line actually adds a validation method to the
base SurveyData class, which means a completely new instance of
SurveyData gets constructed with a validation already present.

Any help would be most appreciated!

Jon

PS the unit test is:

require File.dirname(FILE) + ‘/…/test_helper’

class SurveyDataTest < Test::Unit::TestCase

def test_validateable
sd = SurveyData.new
assert_not_nil sd

 assert_raise(NoMethodError) {
   sd.foo
 }

 assert sd.valid?

 sd.add_required_fields 'foo'

 assert_respond_to sd, :foo
 assert_nothing_raised { sd.foo }

 assert_equal false, sd.valid?, "SurveyData shouldn't be valid

(because we haven’t set ‘foo’ yet)"

 sd.foo = "test"

 assert_equal sd.foo, "test"

 assert sd.valid?

 test_sd = SurveyData.new

 # **** THIS TEST FAILS:
 assert test_sd.valid?, "a different SurveyData should be valid

(because we haven’t yet added any validations to it)"

end

end