I have a mailing-list database that consists of several tables (e.g., clients table, prospects table, etc.). How can I switch between these tables within my mailing-list Rails application? I have a feeling that if I better understood the role of the model I might be able to answer my own question. I''m hoping that getting this question answered will help me in that regard. Thanks for any input. ... doug
Hi-- On May 4, 2009, at 2:38 PM, doug wrote:> I have a mailing-list database that consists of several tables (e.g., > clients table, prospects table, etc.). How can I switch between these > tables within my mailing-list Rails application? > > I have a feeling that if I better understood the role of the model I > might be able to answer my own question. I''m hoping that getting this > question answered will help me in that regard.In Rails, a model normally maps to a table. So if you have a clients table, you have a Client model and if your have a prospects table, you have a Prospect model. Rails infers the table name and columns from the name of the model class. So you can do: send_email_to :clients send_email_to :prospects def send_email_to(whom) model = whom.to_s.camelize.constantize.all.each do |recipient| # recipient is an object of the specified type. Send email at will! end end
> In Rails, a model normally maps to a table.Yes; but, it appears that in this case it would be really nice if I could have a single model and then somehow simply switch between associated tables. (I''m not sure that I''m going to be able to do it.)> Rails infers the table name and columns from > the name of the model class.I understand that default inference. Obviously, if I am able to succeed at what I am trying to do, I would be overriding that default. Thanks for the input. ... doug
Doug Jolley wrote:>> In Rails, a model normally maps to a table. > > Yes; but, it appears that in this case it would be really nice if I > could have a single model and then somehow simply switch between > associated tables. (I''m not sure that I''m going to be able to do it.)Why not just subclass? class Person < ActiveRecord::Base self.abstract_class = true # this will prevent Rails from expecting a "people" table # common features go here end class Client < Person ... end class Prospect < Person ... end That should do the trick! Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
I''ve been working on something like this myself. Depending on how different the two are, it may also just be easier to use Single Table Inheritance? if you decide that abstract classes are better, then I suggest that you do something like this to make your life easier: class Person < ActiveRecord::Base TypesofPeople = ["Client", "Prospect"] def self.abstract_find (person_type, *args) if TypesofPeople.include?(person_type) person_type.constantize.find(*args) else nil end end cheers, -Gabe Marnen Laibow-Koser wrote:> Doug Jolley wrote: >>> In Rails, a model normally maps to a table. >> >> Yes; but, it appears that in this case it would be really nice if I >> could have a single model and then somehow simply switch between >> associated tables. (I''m not sure that I''m going to be able to do it.) > > Why not just subclass? > > class Person < ActiveRecord::Base > self.abstract_class = true # this will prevent Rails from expecting a > "people" table > > # common features go here > end > > class Client < Person > ... > end > > class Prospect < Person > ... > end > > That should do the trick! > > Best, > -- > Marnen Laibow-Koser > http://www.marnen.org > marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org-- Posted via http://www.ruby-forum.com/.
> Why not just subclass?I like that approach. It was essentially what I was playing with when I submitted my original post. The problem with it seems to be that I can''t reference the subclass. Extending your example, I would like to say something like: clients=Client.find(:all) Rails doesn''t like that. It complains that Client is an uninitialized constant. It appears that Rails wants me to say something like: clients=Person.find(:all) IOW, it appears that Rails wants the name of the class to correspond the base name of the model file (i.e., since the name of the model file is person.rb, it wants the class to be Person). Without that correlation, I get the uninitialized constant error. I''m not sure how to get around the problem. If I could; then, I think your suggestion would work just fine. Thanks. ... doug
Doug Jolley wrote: [...]> > IOW, it appears that Rails wants the name of the class to correspond > the base name of the model file (i.e., since the name of the model > file is person.rb, it wants the class to be Person).Yes, this is how Rails works. Put each class definition in a separate file (generally best), or use explicit require statements. [...]> ... dougBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
> if you decide that abstract classes are better, then I suggest that you > do something like this to make your life easier: > > 1: class Person < ActiveRecord::Base > > 2: TypesofPeople = ["Client", "Prospect"] > > 3: def self.abstract_find (person_type, *args) > 4: if TypesofPeople.include?(person_type) > 5: person_type.constantize.find(*args) > 6: else > 7: nil > 8: end > 9: endI really wish that I understood your suggestion especially because it may be what works. I have taken the liberty of adding line numbers. Basically, I understand the code except for line 5. I have no idea what you are doing there. I''m not sure what the person_type and *args are that you are passing to abstract_find. Part of my confusion may stem from the fact that there does not seem to be and ''end'' for your class definition. So, I''m not altogether clear on whether lines 3 through 9 are suggested model code or suggested controller code. Could you please clarify? I do appreciate your suggestion and I have high hopes for it being my salvation. Thanks. ... doug
> Put each class definition in a separate fileBy "separate file" you mean "separate model", right? I guess I could do that. My concern is that if I do I may be opening and closing the connection to the database? Maybe I am and maybe I am not. If I am, maybe I don''t need to worry about it; but, I do. That''s why I wanted to let Rails be in charge of handling the connection to the database. I just want to swap tables. Maybe I should ask a couple of more basic questions: What, if any, are the adverse affects associated with switching models from with an application? If I swap models from within an application, does that result in closing and re-opening the database? Thanks. ... doug
Doug Jolley wrote:>> Put each class definition in a separate file > > By "separate file" you mean "separate model", right? I guess I could > do that. My concern is that if I do I may be opening and closing the > connection to the database? Maybe I am and maybe I am not. If I am, > maybe I don''t need to worry about it; but, I do. That''s why I wanted > to let Rails be in charge of handling the connection to the database. > I just want to swap tables. > > Maybe I should ask a couple of more basic questions: What, if any, > are the adverse affects associated with switching models from with an > application? If I swap models from within an application, does that > result in closing and re-opening the database? > > Thanks. > > ... dougyes, you''ll need to have client.rb (containing the Client class) and prospect.rb (containing the Prospect class) files in app/models . No, the amount of models is not related to connections/disconnections from the database. No matter the amount of models, Rails is handling the connection to the database. The way to swap tables is using one model per table. There are no adverse effects of switching models, the database connection is created when you start the app server (webrick, mongrel, phusion) and closed when you end the server. hope it helps, Maximiliano Guzman -- Posted via http://www.ruby-forum.com/.
> hope it helps,Great answer. Love it! :) I think that I''m a happy camper. Thanks to all who contributed. ... doug
Hey Doug, i believe this is the line that was confusing you? person_type.constantize.find(*args) first, all of what i wrote was model code, and yes, you should break up the two classes into two separate model files, or really, three: Person.rb, Client.rb, and Prospect.rb. Ok, so in that one line, person_type is a string. rails mixes in a function to the String class called "constantize" that changes a string into an actual program token, so, if person_type is "Client" then person_type.constantize is the actual Programming token Client. As long as you define the Client class, rails will then interpret the above line as Client.find(*args) OR Prospect.find(*args) depending on the string passed into abstract_find. The reason i have *args is because it is what the ActiveRecord API specificies as the argument to find - (basically all arguments passed to ActiveRecord find are rolled up into an array, which it then figures out what to do with) so, the above code would allow you to, in your controller, say something like, @person = Person.abstract_find("Client", [normal find arguments go here]) or @person = Person.abstract_find("Prospect", [normal find arguments go here]) the real power comes when you basically let the actual type be dynamically determined by the program/user at run time: @person = Person.abstract_find(specified_person_type, [normal find arguments go here]) I know you had said that you had pretty much figured it out, but i thought this might still be useful. hope it is! -Gabe Doug Jolley wrote:>> 6: � else >> 7: � � nil >> 8: � end >> 9: end > > I really wish that I understood your suggestion especially because it > may be what works. I have taken the liberty of adding line numbers. > Basically, I understand the code except for line 5. I have no idea > what you are doing there. I''m not sure what the person_type and *args > are that you are passing to abstract_find. Part of my confusion may > stem from the fact that there does not seem to be and ''end'' for your > class definition. So, I''m not altogether clear on whether lines 3 > through 9 are suggested model code or suggested controller code. > Could you please clarify? I do appreciate your suggestion and I have > high hopes for it being my salvation. Thanks. > > ... doug-- Posted via http://www.ruby-forum.com/.