Forum: Ruby Anything better than klass = eval("#{task_class}")

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.
01bb0d480d4d2777661a15165b842590?d=identicon&s=25 Paganoni (Guest)
on 2009-04-01 15:17
(Received via mailing list)
Hi, well subject is self explanatory...

Seems a bit to verbose for me but I don't know any other solution to
convert a string containing a class name to a constant of that class
name... Excepted rails way : task_class.camelize.constantize which is
verbose too...
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-04-01 15:34
(Received via mailing list)
On Wed, Apr 1, 2009 at 9:14 AM, Paganoni <noway@fakenullvoid.com> wrote:
> Hi, well subject is self explanatory...
>
> Seems a bit to verbose for me but I don't know any other solution to convert
> a string containing a class name to a constant of that class name...
> Excepted rails way : task_class.camelize.constantize which is verbose too...

>> Object.const_get("String")
=> String

-greg
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-04-01 16:48
(Received via mailing list)
On Apr 1, 2009, at 9:32 AM, Gregory Brown wrote:

>>> Object.const_get("String")
> => String
>
> -greg
>
> --
> BOOK:  http://rubybestpractices.com
> TECH: http://blog.majesticseacreature.com
> NON-TECH: http://metametta.blogspot.com

Or dealing with things like Admin::User or Net::HTTP

   # from Jim Weirich (based on email correspondence)
   def constantize(camel_cased_word)
     camel_cased_word.
       sub(/^::/,'').
       split("::").
       inject(Object) { |scope, name| scope.const_get(name) }
   end

It may be more verbose, but it is much safer that plain 'ole eval()

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-04-01 18:10
(Received via mailing list)
On Wed, Apr 1, 2009 at 10:47 AM, Rob Biedenharn
<Rob@agileconsultingllc.com>wrote:

>>> too...
>> TECH: http://blog.majesticseacreature.com
>      inject(Object) { |scope, name| scope.const_get(name) }
>  end
>
> It may be more verbose, but it is much safer that plain 'ole eval()
>

Actually, I don't think this is entirely right, since const_get will
find
constants found in outer scopes.

For example constantize("MyModule::Object") would return ::Object

So a little better would be:

 def constantize(camel_cased_word)
   camel_cased_word.
     sub(/^::/,'').
     split("::").
     inject(Object) { |scope, name| scope.const_defined?(name) ?
scope.const_get(name) : scope.const_missing(name) }
 end



--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
E1d641bfe4071a5413bac781f06d3fd1?d=identicon&s=25 Sean O'halpin (sean)
on 2009-04-01 18:32
(Received via mailing list)
On Wed, Apr 1, 2009 at 5:09 PM, Rick DeNatale <rick.denatale@gmail.com>
wrote:
>     sub(/^::/,'').
>     split("::").
>     inject(Object) { |scope, name| scope.const_defined?(name) ?
> scope.const_get(name) : scope.const_missing(name) }
>  end

The const_missing handling is a nice touch. I'm pinching this :)
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-04-01 18:38
(Received via mailing list)
On Apr 1, 2009, at 12:09 PM, Rick DeNatale wrote:

>>>> Seems a bit to verbose for me but I don't know any other solution
>>>>>
>> Or dealing with things like Admin::User or Net::HTTP
>>
>   camel_cased_word.
> Twitter: http://twitter.com/RickDeNatale
> WWR: http://www.workingwithrails.com/person/9021-rick-denatale
> LinkedIn: http://www.linkedin.com/in/rickdenatale


irb>   # from Jim Weirich (based on email correspondence)
?>       def constantize(camel_cased_word)
irb>       camel_cased_word.
?>             sub(/^::/,'').
?>             split("::").
?>             inject(Object) { |scope, name| scope.const_get(name) }
irb>     end
=> nil
irb> constantize("MyModule::Object")
NameError: uninitialized constant MyModule
  from (irb):6:in `const_get'
  from (irb):6:in `constantize'
  from (irb):8:in `inject'
  from (irb):3:in `each'
  from (irb):3:in `inject'
  from (irb):3:in `constantize'
  from (irb):8
  from :0
irb>  def constantize(camel_cased_word)
irb>       camel_cased_word.
?>             sub(/^::/,'').
?>             split("::").
?>             inject(Object) { |scope, name| scope.const_defined?
(name) ? scope.const_get(name) : scope.const_missing(name) }
irb>     end
=> nil
irb> constantize("MyModule::Object")
NameError: uninitialized constant MyModule
  from (irb):14:in `constantize'
  from (irb):16:in `inject'
  from (irb):11:in `each'
  from (irb):11:in `inject'
  from (irb):11:in `constantize'
  from (irb):16
  from :0

Except for the slight difference in the backtrace, it looks the same
to me. Why do you think it will return Object for
constantize("MyModule::Object") ?

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-04-01 20:26
(Received via mailing list)
On Wed, Apr 1, 2009 at 12:37 PM, Rob Biedenharn
<Rob@agileconsultingllc.com>wrote:

>>>>
>>>>
>>>>
>>>
>> def constantize(camel_cased_word)
>>  camel_cased_word.
>>    sub(/^::/,'').
>>    split("::").
>>    inject(Object) { |scope, name| scope.const_defined?(name) ?
>> scope.const_get(name) : scope.const_missing(name) }
>> end
>>
>> Except for the slight difference in the backtrace, it looks the same to
> me. Why do you think it will return Object for
> constantize("MyModule::Object") ?


Because it does, if MyModule is actually defined and doesn't define
another
inner constant called Object:

def constantize(camel_cased_word)
  camel_cased_word.

  sub(/^::/,'').
  split("::").
  inject(Object) { |scope, name| scope.const_get(name) }
end


module MyModule
end

constantize("MyModule::Object") # => Object
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-04-01 21:29
(Received via mailing list)
On Apr 1, 2009, at 2:24 PM, Rick DeNatale wrote:

> Because it does, if MyModule is actually defined and doesn't define
> another
> inner constant called Object:


Ah, I see now.  Thanks for the improvement, Rick!

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
01bb0d480d4d2777661a15165b842590?d=identicon&s=25 Paganoni (Guest)
on 2009-04-02 08:31
(Received via mailing list)
le 01/04/2009 16:47, Rob Biedenharn nous a dit:
>>> verbose too...
>        split("::").
>        inject(Object) { |scope, name| scope.const_get(name) }
>    end
>
> It may be more verbose, but it is much safer that plain 'ole eval()
>

Okay, so nothing less verbose ;-) But thanks for all the answers...
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-04-02 16:18
(Received via mailing list)
On Thu, Apr 2, 2009 at 2:30 AM, Paganoni <noway@fakenullvoid.com> wrote:
>>>> a string containing a class name to a constant of that class name...
>>   # from Jim Weirich (based on email correspondence)
> Okay, so nothing less verbose ;-) But thanks for all the answers...
But all of the mentioned suggestions are much better than
eval("ConstantName") in security, performance, and general design.
So if you want something less verbose, just make a method like
C("Whatever") that uses one of those implementations, rather than
forcing Ruby to fire up its parser via eval() just to get a constant.
This topic is locked and can not be replied to.