# Dynamically defined ar classes

**URL:** <https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845>\
**Category:** Rails\
**Created:** [January 30, 2007, 7:01am UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845 "2007-01-30T07:01:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [January 30, 2007, 7:01am UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845/1 "2007-01-30T07:01:24Z")

</div>

I’m using at least 20 primary models, and join models for each  
combination plus some hierarchical ones. I am wondering if it would be  
possible to define the model classes iteratively, and then reopen the  
definitions that I wanted to add code to.

primaries = [:Argument, :Author, :Book, :Category, :Hyperlink, :List,  
:Message, :Ufile, :User, :Language, :Word, :Part\_of\_speech, :Definition,  
:School, :Course, :Meeting, :Task, :Question, :Survey, :Datapoint,  
:Code]  
primaries.each do |primary|  
class primary  
primaries.each { |p| has\_many join\_tables(primary, p); has\_many p,  
:through =\> join\_tables(primary, p) }  
end  
end

where join\_tables is a function that looks into a nested hash to find  
the symbol that I’ve chosen to name each table in the database. I do  
not want to use single table inheritance. I thought that there might be  
some trouble if a controller tried to load a file like argument.rb and  
couldn’t find it, but couldn’t that be addressed by putting this do-end  
loop at a point that always gets executed, like within the application  
controller? Also, I’d need to pluralize the symbols before passing them  
to has\_many; must I convert to\_s and then back or can I call pluralize  
on the symbol? Do I need to call downcase?

Lastly: can variables be interpolated into backticks (system calls)?

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [January 30, 2007, 7:09pm UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845/2 "2007-01-30T19:09:11Z")

</div>

I made a typo: each class should inherit from ActiveRecord::Base

> primaries.each do |primary|  
> class primary \< ActiveRecord::Base  
> primaries.each { |p| has\_many join\_tables(primary, p); has\_many p,  
> :through =\> join\_tables(primary, p) }  
> end  
> end

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [January 30, 2007, 7:23pm UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845/3 "2007-01-30T19:23:35Z")

</div>

I’m not sure I completely understand why you want to do this. If it’s  
to keep things DRY I would question whether this is a bit of an OTT  
optimisation. The models you specified seem generally unrelated and  
as your application grows, you will most likely find that this method  
becomes a hindrance rather than beneficial.

I may be wrong of course, but generally separating your models out and  
defining them individually is a good plan long term. If you want  
something to get started with, I would suggest looking at Dr Nic’s  
Magic Models ([http://magicmodels.rubyforge.org/](http://magicmodels.rubyforge.org/)). This is a plugin  
that automatically creates models from the database schema. Even if  
it’s not what you’re looking for, you may pick up a few tips for what  
you’re trying to do by having a look through the source code.

Steve

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [January 30, 2007, 9:19pm UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845/4 "2007-01-30T21:19:51Z")

</div>

> So: can this work?  
> Yeah, but not in the way you have. You can use the ‘eval’ command to  
> execute ruby code to create your classes:

[‘MyNewClass’].each do |klass|  
model\_string = “class #{klass} \< ActiveRecord::Base; def say\_hello;  
‘Hello!’; end; end;”  
eval(model\_string)  
end

my\_new\_class = MyNewClass.new  
my\_new\_class.say\_hello -\> “Hello!”

You can build up the string using the values defined in your hashes  
and arrays then execute. I’m not sure what effect all this will have  
on the execution time of you app, but try it out and see how you get  
on.

Steve

---

<div class="post-metadata">

**Author:** ![mschwab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/59ef9b/32.png) [@mschwab](https://www.ruby-forum.com/u/mschwab)\
**Post date:** [January 30, 2007, 8:58pm UTC](https://www.ruby-forum.com/t/dynamically-defined-ar-classes/83845/5 "2007-01-30T20:58:49Z")

</div>

I’ve found as my application has grown that adding primary models has  
been so intimidating that it has stifled my progress. I started with  
the first nine and then added a language module, a schoolwork module,  
and plans for a stats module. But I couldn’t settle on whether to  
create join tables for each combination because it would mean I’d have  
three hundred more secondary models to keep straight. Most of them  
don’t have much in the way of unique behavior.

If this scheme worked out, I could add a primary model just by adding a  
symbol to the array primaries, and adding an element to the join\_tables  
hash with twenty symbols containing names for join tables. Then I would  
reopen the models to my heart’s content, and if I wanted to add similar  
methods to several I could use the same iteration idiom, even if all I  
was doing was mixing in a module.

Using magic models might help; thanks for the suggestion. But I still  
think the question should be fair game. There’s one more wrinkle. I  
might subclass the models like so:  
class Primary \< ActiveRecord::Base  
end

then each actual primary model would descend from Primary  
primaries.each do |primary|  
class primary \< Primary  
end  
end

So: can this work?
