7

I want to change the table name of the ActiveRecord model class during request dynamically.


For example, there are many tables having similar structure(columns):

mydb:
  sample_data_12222
  sample_data_12223
  sample_data_12224
  sample_data_12225
  ...

So, what I want to do is...

_1. Defining the base model class like:

class SampleData < ActiveRecord::Base

_2. Changing the target table during request like:

def action_method
  SampleData.set_table_name "sample_data_#{params[:id]}"
  @rows = SampleData.all

It seems that above code is right if it's run on non-threaded environment (like on Passenger/mod_rails). But it's not thread-safe, so it may not work on threaded-environment (like on JRuby-Rack).

Also I tried creating the delived class like this:

def action_method
  @model_class = Class.new(SampleData)
  @model_class.set_table_name "sample_data_#{params[:id]}"
  @rows = @model_class.all

But it cause memory leaks, though the delived model class is not used any more after request was completed. :(


Is there a better way to do that?

3
  • Thank you for your idea, I was looking for something similar (but a little more simple). Hopefully my answer will (still) help you@ Commented Dec 24, 2011 at 23:42
  • Thanks, and sorry for marking your answer accepted. ;) I reached somthing similar to your answer. Commented Sep 7, 2013 at 3:07
  • In case someone needs to play with something similar in the future, see this Q&A: stackoverflow.com/questions/52537951/… Commented Sep 27, 2018 at 15:43

1 Answer 1

7

I would use class variables:

class SampleData < ActiveRecord::Base
  class << self
    @@model_class = {}

    # Create derived class for id
    @@model_class[id] = Class.new(SampleData)
    @@model_class[id].set_table_name "sample_data_#{id}"
    # Repeat for other IDs
  end
end

Now you can use the derived classes over and over, without causing memory leaks.

Depending on your actual situation (eg you do not know the IDs on beforehand), you could check whether the id is already present in the Hash dynamically and add it if not.

Sign up to request clarification or add additional context in comments.

4 Comments

How would you use your origional class as well as the @@model_class[id] class?
@veger this is cool solution but doesnt work for associations. user = SampleData.model_class[44].find(2) /* queries table - sample_data_44 / user.addresses / queries table - addresses, not addresses_44 */
Should I make a loop if I want 10 tables? # Repeat for other IDs
Sure why not, unless you need to do some specific things making the loop impractical. Note that asking non-related-to-the-OP questions should be done in a separate question, especially since this one is very old!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.