# Polymorphic problems with an abstract class

**URL:** <https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147>\
**Category:** Rails\
**Created:** [September 9, 2008, 7:45pm UTC](https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147 "2008-09-09T19:45:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![subbu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@subbu](https://www.ruby-forum.com/u/subbu)\
**Post date:** [September 9, 2008, 7:45pm UTC](https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147/1 "2008-09-09T19:45:55Z")

</div>

This could have been solved earlier. But I couldn’t find a solution.

Lets say I have an abstract base model called ‘Question’ and sub-  
models like Mcq, TrueFalse and FillInTheBlank. Mcq and TrueFalse  
models have a has\_many relation with another model named ‘Choice’  
whereas FillInTheBlank model doesn’t have this. So I have defined the  
choice relation in Mcq and TrueFalse class. While instantiating the  
Mcq and TrueFalse classes in my controllers I don’t know which class  
the instance is going to belong (all I know is it doesn’t belong to  
FillInTheBlank). So I call it like ‘Question.find(params[:id])’. Due  
to the ‘type’ column I get either an ‘Mcq’ instance or a ‘TrueFalse’  
instance. Perfect. But the code breaks down when I call choices method  
on this new instance. It says “NoMethodError: undefined method  
`choices’ for #Mcq:0x3046a84”

However this problem doesn’t come up if I call the find method on the  
correct class i.e. Mcq.find() directly. But as I said earlier the  
problem is I don’t know whether the question is going to be a Mcq or a  
TrueFalse.

One dirty solution I tried is to call find on the abstract class  
(Question.find()), get value of ‘type’ attribute and issue another  
find statement on the correct class (Mcq.find()). But even that didn’t  
solve the problem.

Has anybody faced this kind of a problem? Can someone point me in the  
right direction?

Thanks much.  
subbu

---

<div class="post-metadata">

**Author:** ![subbu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@subbu](https://www.ruby-forum.com/u/subbu)\
**Post date:** [September 9, 2008, 8:21pm UTC](https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147/2 "2008-09-09T20:21:13Z")

</div>

Looks like I have found one solution.

I had 2 definitions for the classes Mcq and TrueFalse, one in separate  
files named mcq.rb and true\_false.rb and another definition in the  
file question.rb (the abstract class itself). I had to have these  
definitions in 2 files because otherwise I couldn’t call the concrete  
classes directly without first loading the abstract class. But that  
apart, my has\_many relation was not in the abstract class file. So it  
was not getting loaded when I issued the find statement on the  
abstract class. But if I issue the find on the concrete class directly  
(without calling the abstract class before) it would’ve loaded the  
has\_many by then and would load the relations properly. Bit tricky. To  
be on the safer side now I have moved all my definitions to the  
abstract class file and keeping the concrete class files empty.

-subbu

---

<div class="post-metadata">

**Author:** ![subbu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@subbu](https://www.ruby-forum.com/u/subbu)\
**Post date:** [September 9, 2008, 11:08pm UTC](https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147/3 "2008-09-09T23:08:49Z")

</div>

the fact that you had 2 definitions each for your concretes looks to be  
your issue… in order to do this and behave well under rails you will  
need exactly 3 files and 3 classes…

I am willing to bet that one of your implementations had the choices()  
method implemented and the other didn’t…

app/models/choice.rb  
class Choice \< ActiveRecord::Base  
abstract true

# no need to implement choices here unless you have a default

implementation  
end

app/models/mcq.rb  
class Mcq \< Choice  
def choices  
end  
end

app/models/true\_false.rb  
class TrueFalse \< Choice  
def choices  
end  
end

hth

ilan

Subbu wrote:

> Looks like I have found one solution.
> 
> I had 2 definitions for the classes Mcq and TrueFalse, one in separate  
> files named mcq.rb and true\_false.rb and another definition in the  
> file question.rb (the abstract class itself). I had to have these  
> definitions in 2 files because otherwise I couldn’t call the concrete  
> classes directly without first loading the abstract class. But that  
> apart, my has\_many relation was not in the abstract class file. So it  
> was not getting loaded when I issued the find statement on the  
> abstract class. But if I issue the find on the concrete class directly  
> (without calling the abstract class before) it would’ve loaded the  
> has\_many by then and would load the relations properly. Bit tricky. To  
> be on the safer side now I have moved all my definitions to the  
> abstract class file and keeping the concrete class files empty.
> 
> -subbu

---

<div class="post-metadata">

**Author:** ![subbu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a88e57/32.png) [@subbu](https://www.ruby-forum.com/u/subbu)\
**Post date:** [September 10, 2008, 8:23am UTC](https://www.ruby-forum.com/t/polymorphic-problems-with-an-abstract-class/148147/4 "2008-09-10T08:23:15Z")

</div>

Ilan,

Mcq and TrueFalse descend from question and not choice. The correct  
structure is below.

app/models/choice.rb  
class Question \< ActiveRecord::Base  
end

app/models/question.rb  
class Question \< ActiveRecord::Base  
self.abstract\_class = true  
end

class Mcq \< Question;end

class TrueFalse \< Question;end

app/models/mcq.rb  
class Mcq \< Question  
has\_many choices  
end

app/models/true\_false.rb  
class TrueFalse \< Question  
has\_many choices  
end

As you can see my question.rb had definitions for all the classes, one  
abstract and 2 concrete but they didn’t have the has\_many relation to  
choices. This relation was present in a different file which was not  
loaded at the time of calling the method. That was causing the issue.

-subbu

On Sep 10, 2:08 am, Ilan B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
