Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically load class using namespaces/subdirectory in Ruby/Rails?

In my Rails 3.1 app (with Ruby 1.9), I have a Deployer1 class that is in a worker subdirectory below the model directory

I am trying to load/instantiate this class dynamically with this code:

clazz = item.deployer_class  # deployer_class is the class name in a string
deployer_class = Object.const_get clazz
deployer = deployer_class.new

If I dont use namespaces, eg something global like this:

class Deployer1
end

Then it works fine (deployer_class="Deployer1") - it can load the class and create the object.

If I try and put it into a module to namespace it a bit, like this:

module Worker
    class Deployer1
    end
end

It doesnt work (deployer_class="Worker::Deployer1") - gives an error about missing constant, which I believe means it cannot find the class.

I can access the class generally in my Rails code in a static way (Worker::Deployer1.new) - so Rails is configured correctly to load this, perhaps I am loading it the wrong way...

EDIT: So, as per Vlad's answer, the solution I went for is:

deployer_class.constantize.new

Thanks Chris

like image 743
Chris Kimpton Avatar asked Sep 30 '11 06:09

Chris Kimpton


2 Answers

try using constantize instead:

module Wtf
  class Damm
  end
end
#=> nil
'Wtf::Damm'.constantize
#=> Wtf::Damm
Object.const_get 'Wtf::Damm'
#=> Wtf::Damm
like image 67
Vlad Khomich Avatar answered Oct 30 '22 13:10

Vlad Khomich


Object does not know a constant named Worker::Deployer1, which is why Object.const_get 'Worker::Deployer1' doesn't work. Object only knows a constant Worker. What does work is Worker.const_get 'Deployer1'.

Vlad Khomisch's answer works, because if you look at the implementation of constantize, this is exactly what it does: it splits the string on '::' and recursively const_get's.

like image 37
Confusion Avatar answered Oct 30 '22 13:10

Confusion