Is it possible to dynamically create new databases and tables within them with Rails?
Or is that a task best done manually?
I’m creating an application which should allow users to store their own statistics information (which can and probably with time will be a lot).
My initial thought was to give each user their own database to keep their data separate from each other due to the possible large quantity of data each user will have.
Good idea? Bad idea? Other ways to do it?
Yes, and yes.
That sounds fine.
Just be careful not to optimise prematurely (ie… make design decisions with a VIEW to the future, but don’t let that both you too much in the present). Chances are when it comes to architecture and optimisation, Ya Aint Gonna Need It, and when you do, it’ll most likely be different than you think it will be now.
Focus more on the classes in your system than how to efficiently store them at the inception/design stage.
Julian
Thanks for replying, Julian.
Can you point me to any resources that describe how to do it?
I agree that I should not optimize prematurely but what I’m considering is which is easier,
to go with dynamically creating databases from the start or to extract data from the single database to new databases later on?
It’s at least something to keep in the back of my mind.
What do you mean by a large quantity of data? Modern databases can
manage vast amounts of data efficiently. It is very rare for the
bottlenecks in a system to be where you expect them to be when you
start out and it is very likely that you will find that the extra work
was a waste of time. Start with a single database and make sure you
have good automated test coverage. Then in the unlikely event that
you find that you do have split the database then you can refactor the
code and the tests will help to ensure that you have not messed
anything up.
Colin
Hi,
You shouldn't attempt to do this if you don't already understand enough Ruby / Rails to do it yourself.
So, I suggest sticking with what you *can* do first.
This might sound like a cop out, but there's very good reason. It's very advanced Rails and you really shouldn't attempt something like this until you understand the basics really well IMHO.
Julian
Thanks for posting, I appreciate the feedback.
I’ll start with keeping everything within a single database and take it from there.
You are right Julian in that I am new with RoR and what I’ve asked for is advanced.
I’m still curious though how creating databases dynamically would be done so if it’s explained anywhere I’d love to read it!
Assuming you are using postgresql you might be interested in this
railscast (paid)
[http://railscasts.com/episodes/389-multitenancy-with-postgresql](http://railscasts.com/episodes/389-multitenancy-with-postgresql)
Which takes advantage of being able to have multiple schemas in
PostgreSQL.
Be aware though that it will make your initial coding more
complicated and will
have knock-on effects for things like testing etc.
Basically, it will do what you want but it will not be free in terms
of development effort.
I echo other statements that this may be premature optimisation,
look at the railscast, give
it a try yourself and see if the trade-off is good enough for you.
(If you do not want to pay for railscasts then have a look at this
gem: https://github.com/influitive/apartment)
Okay…
So to do this, you need to understand meta-programming to a degree because that’s what you’re doing.
In normal Rails, you’d create a model as part of the development process, but what you’re doing is creating some code that creates models itself (ie one level of abstraction higher than normal).
The equivalent straight ruby comparison is: (compare 1, with 2, below):
- Creating a class (this is normal programming)
class Cat
def hi
puts ‘meow’
end
end
You can then create new Cat objects like this:
furrycat = Cat.new
and make it meow like this:
furrycat.hi
- Creating a piece of code that creates a class (this is meta-programming)
a_class = Class.new
hi_method_block = Proc.new{ puts ‘meow’ }
a_class.send(:define_method, :hi, &hi_method_block)
You can then create new “Cat” objects like this:
furrycat = a_class.new
and make it meow like this:
furrycat.hi
We have toyed with creating separate databases for each customer as our combined one is starting to get quite large. In our case, the models will always be the same no matter which database you are connecting to, so there isn't any meta-programming involved. It's just a case of switching databases to the correct one for that customer once they log into the system.
One thing to consider is that shared data needs to go somewhere (sessions, username/passwords etc) as well.
Cheers
Simon
That kind of scenario was what I had initially in mind. Everyone has
the same models, just not the same database.
Hello!
I know three years have passed, but I am looking to do exactly what you proposed on your first post, so I am interested in knowing if you have managed to so and if you did, how did you do it?
Thanks in advance.
quinta-feira, 4 de Abril de 2013 às 05:24:18 UTC-4, Johan Vauhkonen escreveu:
Faced a similar problem today and thought I’d post my solution. To figure this out I looked through the rails database.rake codebase: rails/databases.rake at main · rails/rails · GitHub
ActiveRecord::Base.configurations[“newdb”] = {
“adapter” => ‘mysql2’,
“encoding” => ‘utf8’,
“reconnect” => false,
“database” => ‘newdb’,
“pool” => 5,
“username” => ‘[username]’,
“password” => ‘[password]’,
“host” => ‘127.0.0.1’,
“port” => 3306,
}
ActiveRecord::Tasks::DatabaseTasks.env = ‘newdb’
ActiveRecord::Tasks::DatabaseTasks.create # Creates the database, empty.
ActiveRecord::Tasks::DatabaseTasks.migrate # Runs migrations against the new empty database.
``