Is there an neater way to achieve this without using that clunky eval
and inline substitution?
def test_confirmation(object, test_attribute, test_values = {},
attributes = {})
instance = eval("#{object}.new(attributes)")
test_values.each do |value|
instance.send("#{test_attribute}=", value)
instance.send("#{test_attribute}_confirmation=", value)
assert !instance.save
assert instance.errors.invalid?(test_attribute)
end
end
Just feels a little clunky and wanted some pointers to improve my ruby.
Any thoughts would be useful.
On Jun 11, 2006, at 3:03 PM, James McCarthy wrote:
instance = eval("#{object}.new(attributes)")
instance = Object.const_get(object).new(attributes)
Hope that helps.
James Edward G. II
On Jun 11, 2006, at 4:03 PM, James McCarthy wrote:
assert instance.errors.invalid?(test_attribute)
end
end
Just feels a little clunky and wanted some pointers to improve my
ruby.
Any thoughts would be useful.
You can pass classes as arguments to functions:
test_confirmation(SomeClass, …)
instance = object.new(attributes)
If the problem is you have to get a string, use const_get
e.g.
Object.const_get(object).new(attributes)
The only problem with this is that it doesn’t work for nested
constants (e.g. Net::HTTP). So to generalize that you do
instance = object.split(/::/).inject(Object) { |base, child|
base.const_get(child) }.new(attributes)
the #send s seem fine to me, much better than just straight eval’ing
the stuff.
Joel VanderWerf wrote:
object.send(:new, attributes)
Duh. Of course, as Logan said, you can just object.new(attributes). And
unlike me he was not lazy and wrote out the inject solution.
James McCarthy wrote:
Is there an neater way to achieve this without using that clunky eval
and inline substitution?
def test_confirmation(object, test_attribute, test_values = {},
attributes = {})
instance = eval("#{object}.new(attributes)")
If object is supposed to be a class:
object.send(:new, attributes)
If object is a string that names a class you will have to use const_get
to avoid eval. Check the archives for a good way to do that using
inject.
test_values.each do |value|
instance.send("#{test_attribute}=", value)
instance.send("#{test_attribute}_confirmation=", value)
AFAIK there is no better way to call setter methods, if the name of the
method is a parameter. If you only need to set the instance vars, you
can use #instance_variable_set, but that’s not the same thing as calling
the accessor method.
HTH.
On Mon, Jun 12, 2006 at 05:03:43AM +0900, James McCarthy wrote:
} Is there an neater way to achieve this without using that clunky eval
} and inline substitution?
}
} def test_confirmation(object, test_attribute, test_values = {},
} attributes = {})
} instance = eval(“#{object}.new(attributes)”)
} test_values.each do |value|
} instance.send(“#{test_attribute}=”, value)
} instance.send(“#{test_attribute}_confirmation=”, value)
} assert !instance.save
} assert instance.errors.invalid?(test_attribute)
} end
} end
}
} Just feels a little clunky and wanted some pointers to improve my
ruby.
} Any thoughts would be useful.
Take a look at
http://redcorundum.blogspot.com/2006/05/kernelqualifiedconstget.html
–Greg