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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
EDIT: last line of ''dynamically defined classes'' code should read puts a.valid? --> true -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Earle Clubb wrote:> EDIT: last line of ''dynamically defined classes'' code should read > > puts a.valid? --> trueYour 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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hi -- On Mon, 17 Mar 2008, Earle Clubb wrote:> > 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?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 for details. Berlin dates coming soon! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hi -- On Mon, 17 Mar 2008, Earle Clubb wrote:> > 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?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 for details. Berlin dates coming soon! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hi -- On Mon, 17 Mar 2008, Earle Clubb wrote:> ------------------------------ > 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 > endTry 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 for details. Berlin dates coming soon! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
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 Clubb <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org>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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---