# AR: static vs. dynamic model generation

**URL:** <https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209>\
**Category:** Rails\
**Created:** [March 17, 2008, 10:31pm UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209 "2008-03-17T22:31:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 17, 2008, 10:31pm UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/1 "2008-03-17T22:31:03Z")

</div>

I have a project where there are an arbitrary number of databases, all  
of which have the same schema, but different data. In light of this,  
I’m trying to generate sets of models on the fly (one set per database).  
I need to be able to access several databases simultaneously without the  
connections overwriting each other. The traditional method for  
accessing multiple databases is to subclass ActiveRecord::Base as an  
abstract class for making the connection, then subclassing the abstract  
class to make the models. This isn’t scalable, however, as I would have  
to manually create a new set of classes for each database.

I can generate classes on the fly and achieve the same effect as the  
traditional method, but for some reason ActiveRecord won’t pick up my  
validations.

Below is my test code for both methods:

* * *

## statically defined classes

require ‘rubygems’  
require ‘active\_record’

class DbBase \< ActiveRecord::Base  
self.abstract\_class = true  
end

class AudioFile \< DbBase  
validates\_presence\_of :name  
end

DbBase.establish\_connection(:adapter =\> ‘sqlite3’, :database =\>  
‘test1.db’)  
a = AudioFile.new  
puts a.valid? --\> false

* * *

## dynamically defined classes

require ‘rubygems’  
require ‘active\_record’

DbBase = Class.new(ActiveRecord::Base) do  
self.abstract\_class = true  
end

AudioFile = Class.new(DbBase) do  
validates\_presence\_of :name  
end

DbBase.establish\_connection(:adapter =\> ‘sqlite3’, :database =\>  
‘test1.db’)  
a = AudioFile.new  
puts a.valid?

* * *

Any ideas on how I can do this dynamic definition without ActiveRecord  
ignoring my validations?

Thanks,  
Earle

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 17, 2008, 10:34pm UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/2 "2008-03-17T22:34:49Z")

</div>

EDIT: last line of ‘dynamically defined classes’ code should read

puts a.valid? --\> true

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 18, 2008, 3:16am UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/3 "2008-03-18T03:16:34Z")

</div>

Earle C. wrote:

> EDIT: last line of ‘dynamically defined classes’ code should read
> 
> puts a.valid? --\> true

Your problem domain is not anything like the “usual” way that you  
describe. In the usual way, (with the subclassing of AR::Base, the  
different tables represent different models but in your case, you have  
the same models across separate dbs.

I would approach this like this…

class AudioFile \< ActiveRecord::Base  
abstract\_class = true

# all AudoFile code validation code goes here…

end

[:db1, :db2, :db3].each do |db|  
Class.new(“AudioFile#{db}”) do  
establish\_connection db  
end  
end

hth

ilan

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 18, 2008, 4:50am UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/4 "2008-03-18T04:50:36Z")

</div>

Hi –

On Mon, 17 Mar 2008, Earle C. wrote:

> require ‘rubygems’  
> DbBase.establish\_connection(:adapter =\> ‘sqlite3’, :database =\>  
> require ‘active\_record’  
> ‘test1.db’)  
> a = AudioFile.new  
> puts a.valid?
> 
> * * *
> 
> Any ideas on how I can do this dynamic definition without ActiveRecord  
> ignoring my validations?

I don’t know exactly but in messing around with it I’ve noticed that  
the validations don’t run even if you take out the second level of  
inheritance:

AudioFile = Class.new(ActiveRecord::Base) do  
validates\_presence\_of :name  
end

AudioFile.establish\_connection(:adapter =\> ‘sqlite3’, :database =\>  
‘test1.db’)  
a = AudioFile.new  
puts a.valid? # true

Not an answer to your question, but maybe reducing it will pinpoint  
the issue.

David

–  
Upcoming Rails training from David A. Black and Ruby Power and Light:  
ADVANCING WITH RAILS, April 14-17 2008, New York City  
CORE RAILS, June 24-27 2008, London (Skills Matter)  
See [http://www.rubypal.com](http://www.rubypal.com) for details. Berlin dates coming soon!

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 20, 2008, 6:39am UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/5 "2008-03-20T06:39:37Z")

</div>

Hi –

On Mon, 17 Mar 2008, Earle C. wrote:

> AudioFile = Class.new(DbBase) do  
> validates\_presence\_of :name  
> end

Try changing that to:

(AudioFile = Class.new(DbBase)).class\_eval do  
validates\_presence\_of :name  
end

David

–  
Upcoming Rails training from David A. Black and Ruby Power and Light:  
ADVANCING WITH RAILS, April 14-17 2008, New York City  
CORE RAILS, June 24-27 2008, London (Skills Matter)  
See [http://www.rubypal.com](http://www.rubypal.com) for details. Berlin dates coming soon!

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [April 1, 2008, 3:27am UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/6 "2008-04-01T03:27:16Z")

</div>

Hello Earle,

I have the same problem to solve. I was wondering if you ever came up  
with a solution?

Thanks,

Curtis

On Mar 17, 5:31 pm, Earle C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [April 1, 2008, 3:50pm UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/7 "2008-04-01T15:50:48Z")

</div>

Curtis wrote:

> Hello Earle,
> 
> I have the same problem to solve. I was wondering if you ever came up  
> with a solution?
> 
> Thanks,
> 
> Curtis
> 
> On Mar 17, 5:31ï¿½pm, Earle C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

I did find a solution. When I was using a single database, I had all of  
my models wrapped up in a module so I could have cleaner module-level  
methods for connecting to the db, getting/setting flags in the db, etc.  
I turns out that if you make a copy of the module and change the module  
and db name, you get a whole new isolated connection. So I wrote a  
method to copy the module and change the name. Seems to work well. If  
you need more info, let me know. Thanks to all who helped out with  
this.

Earle

---

<div class="post-metadata">

**Author:** ![eclubb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/ecc23a/32.png) [@eclubb](https://www.ruby-forum.com/u/eclubb)\
**Post date:** [March 19, 2008, 3:44am UTC](https://www.ruby-forum.com/t/ar-static-vs-dynamic-model-generation/132209/8 "2008-03-19T03:44:37Z")

</div>

Hi –

On Mon, 17 Mar 2008, Earle C. wrote:

> require ‘rubygems’  
> DbBase.establish\_connection(:adapter =\> ‘sqlite3’, :database =\>  
> require ‘active\_record’  
> ‘test1.db’)  
> a = AudioFile.new  
> puts a.valid?
> 
> * * *
> 
> Any ideas on how I can do this dynamic definition without ActiveRecord  
> ignoring my validations?

I think that what’s happening is that when you do the AF =  
Class.new(DbBase) version, the rhs gets evaluated before the  
assignment (of course). That means that a bunch of inheritance  
callback stuff gets executed with respect to an anonymous class. The  
part I haven’t found is why that matters, since the class then gets  
bound to a constant… but it does appear to matter.

So – and I present this more as a way to spot the problem, than a way  
to solve it elegantly – you can re-execute some inheritance callback  
code, using the new class.

AudioFile = Class.new(ActiveRecord::Base)  
ActiveRecord::Base.send(:inherited\_with\_inheritable\_attributes,  
AudioFile)

I’m still not sure exactly what makes the inheritance hooks care  
whether the new subclass is anonymous or not. Nor do I know whether  
re-executing that method is harmful… but it’s ugly enough not to be  
a long-term solution anyway 🙂

David

–  
Upcoming Rails training from David A. Black and Ruby Power and Light:  
ADVANCING WITH RAILS, April 14-17 2008, New York City  
CORE RAILS, June 24-27 2008, London (Skills Matter)  
See [http://www.rubypal.com](http://www.rubypal.com) for details. Berlin dates coming soon!
