Sam 山
Sam 山

Reputation: 42865

Dynamically Access Class Module In Ruby

My base class is Premade which has two subclasses: PremadeController and PremadeControllerSession. They are very similar. For example. They both need to build records in MySQl in batches of 1000, but I want PremadeControllers to get built before so I have them going to different queues in Resque.

So the two sub classes look like this:

class PremadeController < Premade

  def self.maintain
    ((max_premade_count - premade_count)/batch_size).times do
      Resque.enqueue(Workers::BuildPremadeControllerJob)
    end
  end

end 

And:

class PremadeSessionController < Premade

  def self.maintain
    ((max_premade_count - premade_count)/batch_size).times do
      Resque.enqueue(Workers::BuildPremadeControllerSessionJob)
    end
  end

end 

The only difference between those methods is the worker class (i.e. BuildPremadeControllerSessionJob and BuildPremadeControllerJob)

I've tried to put this in the parent and dynamically defining the constant, but it does not work probably due to a scope issue. For example:

class Premade

  def self.maintain
    ((max_premade_count - premade_count)/batch_size).times do
      Resque.enqueue(Workers::)
    end
  end

end

What I want to do is define this method in the parent, such as:

def self.maintain
  ((max_premade_count - premade_count)/batch_size).times do
    Resque.enqueue(Workers::build_job_class)
  end
end

Where build_job_class is defined in each subclass.

Please don't tell me to change Resque's worker syntax because that is not the question I'm asking.

Upvotes: 0

Views: 686

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84114

One way of doing this would be to defined a build_job_class class method on your 2 classes that returns the appropriate worker class, i.e. PremadeSessionController would look like

class PremadeSessionController
  def self.build_job_class
    Workers::BuildPremadeControllerSessionJob
  end
end

Then change your maintain method to

def self.maintain
  ((max_premade_count - premade_count)/batch_size).times do
    Resque.enqueue(build_job_class)
  end
end

Upvotes: 1

x1a4
x1a4

Reputation: 19475

You should be able to do this with const_get -

klass = Workers.const_get "Build#{self.name}Job"

Upvotes: 3

Related Questions