Forum: Ruby Is there a better way...

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
James M. (Guest)
on 2006-06-12 00:03
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.
James G. (Guest)
on 2006-06-12 00:27
(Received via mailing list)
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
Logan C. (Guest)
on 2006-06-12 00:28
(Received via mailing list)
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 (Guest)
on 2006-06-12 00:31
(Received via mailing list)
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.
Joel VanderWerf (Guest)
on 2006-06-12 00:35
(Received via mailing list)
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.
Gregory S. (Guest)
on 2006-06-12 00:35
(Received via mailing list)
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/kernelqual...

--Greg
This topic is locked and can not be replied to.