clazz = Array
the variable clazz holds a Class object representing the class Array.
I want to start with a string like this.
name = 'Array'
clazz = ???
--
R. Mark Volkmann
Partner, Object Computing, Inc.
For top-level objects, this is as simple as:
name = 'Array'
klass = Object.const_get(name)
p klass # => Array
For nested values, it's:
name = 'Transaction::Simple::Group'
klass = name.split(/::/).inject(Object) { |k, n| k.const_get(n) }
p klass # => Transaction::Simple::Group
-austin
--
Austin Ziegler * halos...@gmail.com
* Alternate: aus...@halostatue.ca
ObjectSpace.each_object {|obj|
break obj if Class === obj and obj.name == clazz
}
But I'm still young. There might be a non-crappy way.
Devin
> How can I create a Class object from a String that contains the
> name of a class?
> For example, after
>
> clazz = Array
>
> the variable clazz holds a Class object representing the class Array.
> I want to start with a string like this.
>
> name = 'Array'
> clazz = ???
clazz = Object.const_get(name)
Hope that helps.
James Edward Gray II
Quite right. There is also the eval (evil?) method:
clazz = eval(name)
BTW, I've wondered why Object.const_get doesn't honor
the X::Y::Z form. It's unambiguous and I can't see a
good reason not to decipher it.
Hal
> BTW, I've wondered why Object.const_get doesn't honor
> the X::Y::Z form. It's unambiguous and I can't see a
> good reason not to decipher it.
RCR?
One possible reason: when you call Object#const_get, you're asking
Object to fetch a constant in its namespace. It might not be logical
to allow recursive decent. (I'm not convinced of this, though... it's
just a thought :)
What about adding a Kernel#const_get that does this? That might
separate things a little better; a global method that decodes any
class name, nested or not, based on current context.
cheers,
Mark
At Fri, 24 Jun 2005 16:07:18 +0900,
Mark Hubbart wrote in [ruby-talk:146353]:
> What about adding a Kernel#const_get that does this? That might
> separate things a little better; a global method that decodes any
> class name, nested or not, based on current context.
Kernel also is one of modules.
$ ruby -e 'p Kernel.const_get("Object")'
Object
Index: object.c
===================================================================
RCS file: /cvs/ruby/src/ruby/object.c,v
retrieving revision 1.169
diff -U2 -p -r1.169 object.c
--- object.c 11 May 2005 07:00:32 -0000 1.169
+++ object.c 24 Jun 2005 04:37:33 -0000
@@ -1715,9 +1715,46 @@ rb_mod_attr_accessor(argc, argv, klass)
}
+static ID
+mod_const_id(namep)
+ volatile VALUE *namep;
+{
+ VALUE tmp, name = *namep;
+ ID id;
+
+ switch (TYPE(name)) {
+ case T_STRING:
+ break;
+ case T_FIXNUM:
+ rb_warn("do not use Fixnums as Symbols");
+ id = FIX2LONG(name);
+ if (!rb_id2name(id)) {
+ rb_raise(rb_eArgError, "%ld is not a symbol", id);
+ }
+ return id;
+ case T_SYMBOL:
+ return SYM2ID(name);
+ default:
+ tmp = rb_check_string_type(name);
+ if (NIL_P(tmp)) {
+ rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING(rb_inspect(name))->ptr);
+ }
+ *namep = name = tmp;
+ }
+ if (RSTRING(name)->ptr && strchr(RSTRING(name)->ptr, ':'))
+ return 0;
+
+ id = str_to_id(name);
+ if (!rb_is_const_id(id)) {
+ rb_name_error(id, "wrong constant name %s", rb_id2name(id));
+ }
+
+ return id;
+}
+
/*
* call-seq:
* mod.const_get(sym) => obj
*
- * Returns the value of the named constant in <i>mod</i>.
+ * Returns the value of the named constant under <i>mod</i>.
*
* Math.const_get(:PI) #=> 3.14159265358979
@@ -1728,9 +1765,10 @@ rb_mod_const_get(mod, name)
VALUE mod, name;
{
- ID id = rb_to_id(name);
+ ID id = mod_const_id(&name);
- if (!rb_is_const_id(id)) {
- rb_name_error(id, "wrong constant name %s", rb_id2name(id));
+ if (!id) {
+ return rb_path2const(RSTRING(name)->ptr, mod, Qtrue);
}
+
return rb_const_get(mod, id);
}
Index: variable.c
===================================================================
RCS file: /cvs/ruby/src/ruby/variable.c,v
retrieving revision 1.121
diff -U2 -p -r1.121 variable.c
--- variable.c 13 May 2005 08:56:14 -0000 1.121
+++ variable.c 24 Jun 2005 04:17:48 -0000
@@ -234,11 +234,21 @@ rb_set_class_path(klass, under, name)
VALUE
-rb_path2class(path)
+rb_path2const(path, cbase, idcheck)
const char *path;
+ VALUE cbase;
+ int idcheck;
{
const char *pbeg, *p;
ID id;
- VALUE c = rb_cObject;
+ VALUE c = cbase;
+ switch (TYPE(cbase)) {
+ case T_MODULE:
+ case T_CLASS:
+ break;
+ default:
+ rb_raise(rb_eTypeError, "class or module required but %s given",
+ rb_obj_classname(cbase));
+ }
if (path[0] == '#') {
rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
@@ -249,6 +259,9 @@ rb_path2class(path)
while (*p && *p != ':') p++;
- str = rb_str_new(pbeg, p-pbeg);
+ *(volatile VALUE *)&str = rb_str_new(pbeg, p-pbeg);
id = rb_intern(RSTRING(str)->ptr);
+ if (idcheck && !rb_is_const_id(id)) {
+ rb_name_error(id, "wrong constant name %s", RSTRING(str)->ptr);
+ }
if (p[0] == ':') {
if (p[1] != ':') goto undefined_class;
@@ -258,7 +271,15 @@ rb_path2class(path)
if (!rb_const_defined(c, id)) {
undefined_class:
- rb_raise(rb_eArgError, "undefined class/module %.*s", p-path, path);
+ if (cbase == rb_cObject) {
+ rb_raise(rb_eArgError, "undefined class/module %s",
+ RSTRING(str)->ptr);
+ }
+ else {
+ rb_raise(rb_eArgError, "undefined class/module %s under %s",
+ RSTRING(str)->ptr, rb_class2name(c));
+ }
}
c = rb_const_get_at(c, id);
+ if (!*p) break;
switch (TYPE(c)) {
case T_MODULE:
@@ -273,4 +294,21 @@ rb_path2class(path)
}
+VALUE
+rb_path2class(path)
+ const char *path;
+{
+ VALUE c = rb_path2const(path, rb_cObject, Qfalse);
+
+ switch (TYPE(c)) {
+ case T_MODULE:
+ case T_CLASS:
+ break;
+ default:
+ rb_raise(rb_eTypeError, "%s does not refer class/module", path);
+ }
+
+ return c;
+}
+
void
rb_name_class(klass, id)
Index: intern.h
===================================================================
RCS file: /cvs/ruby/src/ruby/intern.h,v
retrieving revision 1.170
diff -U2 -p -r1.170 intern.h
--- intern.h 12 Jun 2005 16:56:05 -0000 1.170
+++ intern.h 24 Jun 2005 03:57:26 -0000
@@ -504,6 +504,7 @@
VALUE rb_mod_name _((VALUE));
VALUE rb_class_path _((VALUE));
void rb_set_class_path _((VALUE, VALUE, const char*));
+VALUE rb_path2const _((const char*, VALUE, int));
VALUE rb_path2class _((const char*));
void rb_name_class _((VALUE, ID));
VALUE rb_class_name _((VALUE));
--
Nobu Nakada
I actually meant a private instance method defined in Kernel, like
Kernel#warn et al. I was thinking that it might make sense to call
either
SomeNamespace.const_get("SomeConst")
or a plain
const_get("Nifty::Nested::Namespaces")
which could be done from anywhere, and would use the current scope.
But differentiating between the two looks like it may be be more
confusing than it's worth (especially since the worth was dubious
anyway). I un-submit the idea.
cheers,
Mark
lib/facet/object/constant.rb in the Facets gem.
-g.
> checkout
>
> lib/facet/object/constant.rb in the Facets gem.
Thanks! It looks like this will do what I want.
After running "gem install facets" I found that the file constant.rb was placed
in C:\Ruby\Ruby1.8.2-15\lib\ruby\gems\1.8\gems\facets-0.7.2\lib\facet\object.
Just thought I'd share this in case anyone had trouble finding it.
there is an even better alternative too:
lib/facet/class/by_name.rb
or
lib/facet/module/by_name.rb
(dont't remember exactly)
this allows you to do:
clazz = Class.by_name('Namespace::MyClass')
regards,
George.
> Hi,
>
> At Fri, 14 Oct 2005 01:21:55 +0900,
> Ara.T.Howard wrote in [ruby-talk:160438]:
>> you can 'fix' broken code by creating a wrapper that does
>>
>> #! /usr/bin/env ruby
>> STDOUT.sync = true
>> exec(ARGV.join(' '))
>
> IO#sync flag can't affect other processes.
sheesh. you're right of course... how does using a pty affect this?
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
At Fri, 14 Oct 2005 11:57:27 +0900,
Ara.T.Howard wrote in [ruby-talk:160549]:
> > IO#sync flag can't affect other processes.
>
> sheesh. you're right of course... how does using a pty affect this?
$ ruby -e 'IO.popen(%[ruby -e "p STDOUT.tty?"]) {|i| p i.read}'
"false\n"
$ ruby -rpty -e 'PTY.spawn(%[ruby -e "p STDOUT.tty?"]) {|i,o| p i.read}'
"true\r\n"
--
Nobu Nakada