views:

127

answers:

3

I'm working on creating my first plugin for rails. I'm still pretty new to ruby and I was wondering if its possible to get the inheriting class?

For example, I'm trying to create a plugin that will allow unit testing and functional testing when you are not using migrations. What I'm trying to do is initialize a class variable named controller to be initialized to the type of controller that is being tested.

If I have a base class ControllerTest:

class ControllerTest < Test::Unit::TestCase
  attr_accessor :controller

  def initialize
    super
    @controller = "call function that will find the inheriting classes name and create an instance of that controller type."
  end
end

So what I'm currently stuck on is getting the name of the inheriting class. Is this possible? And if not, does anyone know another way on how I could go about implementing this?

Thanks in advance.

+1  A: 

If you wish to get the name of the class you're in at the moment, you can use self.class.name. If you wish to get the superclasses, you can use the array self.class.ancestors, e.g. self.class.ancestors[1].name. The immediate superclass is also available as self.superclass.

Edit, added example:

class ControllerTest
  attr_accessor :controller
  def initialize
    super
    @controller = eval "#{self.class.name}Controller.new(self)"
  end
end

class Foo <ControllerTest
end
class Bar <ControllerTest
end

class Controller
  def initialize (o)
    puts "Created #{self.class} to control #{o.class.name}"
  end
end

class FooController <Controller
end
class BarController <Controller
end

foo = Foo.new
bar = Bar.new

This outputs

Created FooController to control Foo
Created BarController to control Bar
Arkku
For future reference, the easiest way is to just use the "inherited" callback.
fig
@fig-gnuton: If so, post the example to accomplish the *same thing* (= obtain a specific type of controller based on the name of the inheriting class) using that; that would be actually helpful for anyone who finds this question later and actually means to ask how to use the `inherited` callback instead of what this question was about.
Arkku
A: 

Very simple: use the "inherited" callback.

From the RDoc for the Class class: inherited(subclass): Callback invoked whenever a subclass of the current class is created.

Example:

   class Foo
      def self.inherited(subclass)
         puts "New subclass: #{subclass}"
      end
   end

   class Bar < Foo
   end

   class Baz < Bar
   end
produces:

   New subclass: Bar
   New subclass: Baz

http://ruby-doc.org/core/classes/Class.html#M002785

fig
@fig-gnuton: As the OP accepted my answer, it seems that your downvote for “not answering the question” may have been somewhat incorrect.
Arkku
lol, yours is still the poorer choice. The OP just apparently doesn't know how to select an answer. :)
fig
@fig-gnuton: The OP selected the only answer that fits the code example posted in his question. The way you (and any number of other posters) interpret the (admittedly ambiguous) wording at the end does not change what the OP *meant* to ask. So, even though your answer is perfectly valid for the question you *thought* he asked, it just means that the question may not have been very clear to everyone, but it resulted in an acceptable answer.
Arkku
(Of course you could argue for a different design of the OP's code and amend your answer to illustrate how this solution could replace it, but right now it does not result in “@controller to be initialized to the type of controller that is being tested”. Showing how to use it for that would be more constructive than downvoting the question and every different interpretation of it…)
Arkku
I disagree. Yours is still the poor choice given the wording of both the title of the post and the question itself (including the code example).
fig
I fully agree that the title is ambiguous as it does not specify the context in which to get the inheriting class; it could just as well mean at the moment of inheritance (as per your answer). However, the code example shows that the OP wants to get the name of the class in the `initialize` method in order to create an instance of another class and assign it to `@controller`. If you believe your answer fits this example, I would be genuinely interested in seeing how you'd use it in that context.
Arkku
A: 

I believe you'll need to catch the classes as they're being defined...

From the RDoc for the Class class:

inherited(subclass)
Callback invoked whenever a subclass of the current class is created.

Example:

   class Foo
      def self.inherited(subclass)
         puts "New subclass: #{subclass}"
      end
   end

   class Bar < Foo
   end

   class Baz < Bar
   end
produces:

   New subclass: Bar
   New subclass: Baz
Mike Cargal
Duplicated the same answer posted earlier.
fig
When I began posting this answer yours was not there. Sorry if you were offended, but I didn't see your answer until I posted mine.
Mike Cargal