Re: dynamic tablenames

Russell Norris
Mon, 29 Jan 2007 13:37:39 -0000

I''ve come to the same result as you with setting the table_name via a
filter
but I still go through the Site model to change the child table_names
because, in my case, the child table names all use an attribute of the site
instance.[Site#db_name, which in turn comes from Site#host].

As far as the self.table_name methodology. I had a lot of trouble with that
and finally gave up because it wants to set that when the model loads and
since I''m actually calling an attribute from another model to get a
string,
the whole thing would collapse on me. I had the same problem with custom
finders until I came across a post somewhere that talked about using single
rather than double quotes. I really should have mentioned that earlier too.

RSL

On 1/28/07, John-Scott Atlakson
<john.scott.atlakson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:
>
> On 1/27/07, Russell Norris
<sconds-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >
> > What''s the criteria for which models need a new table
name/prefix? If it
> > centers around another model then you can put a table_prefix attribute
on
> > that model and call it thusly:
> >
> > def self.set_tables
> >   OtherModel.set_table_name "#{table_prefix}_othermodels"
> > end
> >
> > Don''t use table_name_prefix as it sets ActionRecord::Base
itself and not
> > the specific model as you might think. Lots of fun confusion on that
for me.
> > Also, you can''t [or I couldn''t figure out how to]
set the table_name on the
> > model itself. For me, the models that needed new table names
[databases
> > actually] were all related to what site was being used so my Site
model has
> > the set_tables method. Call that method from a filter on the
appropriate
> > controller methods and voila! On-the-fly table name changes. If you
have a
> > relationship between the models, you might also need to tweak your
> > associations code like this:
> >
> > class Whatever
> >   has_many :othermodels, :finder_sql => ''SELECT
> > #{table_name}_othermodels.* FROM #{table_name}_othermodels WHERE
> > #{table_name}_othermodels.whatever_id = #{id}''
> >
> > I hope that''s not too obtuse. It''s just that my code
uses this
> > functionality to change databases and I don''t want to paste
it and have you
> > thinking that it''s merely for changing table names. However,
if anyone is
> > wondering... If you do need to change the database, you don''t
have to
> > establish a new connection but can use
Model.set_table_name"#{db_name}.table_name".  You can use the same
trick in the association to
> > select across two databases.
> >
> > God, I hope that wasn''t too obscure. Apologies in advance.
> >
> > RSL
> >
>
>
> Hmm, I posted a reply using the Google Groups interface and it''s
not
> appearing (even though my first reply to this post came through just fine).
> Lots of posts elsewhere about this annoying Google Groups issue. So at the
> risk of repeating myself, I''ll try sending an email reply to the
group to
> see if it goes through or disappears into the ether.
>
> Anyway, first off, thanks for your reply. My particular situation is that
> I have separate tables for individual US states with the two letter state
> abbreviation as table prefixes ( e.g. ''ny_things'',
''ca_things''). For a
> variety of reasons these tables can''t be merged into a single
table. Rather
> than define (essentially the same) models for every state, I''d
rather just
> have the user select a state, which will the set the state abbreviation in
> the users session data. From then on, all tables needing a prefix will be
> dynamically set according to the session data. Some tables do not need a
> prefix at all, so yes, I ran into the same problem trying to set
> ''table_name_prefix'' on an individual model and found it
was being prefixed
> to all table names.
>
> So for my first stab at a solution, I''m using a before_filter in
my
> controllers which call a private method in application.rb (so it can be
> shared between several controllers) which calls the
''table_name'' methods for
> those models needing this:
>
> class ApplicationController < ActionController::Base
>   def set_table_names
>     Thing.table_name = "#{session[:state_abbreviation]}_things"
>   end
> end
>
> Before this method is called, I call another before_filter method that
> makes sure the the session variable is set and valid. If not, it redirects
> the user to select an appropriate value. This is working perfectly for now.
> I''m using a regular expression to ensure that the state
abbreviation is in
> fact two and only two lower case letters before it is set in the session,
so
> I think I''m fairly safe with this approach.
>
> As far as setting the table name within a model, I''ve always been
able to
> just do:
>
> class ExampleModel < ActiveRecord::Base
>   self.table_name =
"some_crazy_table_name_not_conforming_to_conventions"
> end
>
> Cheers,
> John-Scott
> --
> http://blog.portable-eggplant.org