One set of source code with multiple instances


#1

Hi there, we made a PHP and Impakt2 based web content management system
for schools with specific features that work really well for schools.
The way I designed it was so there was one central set of source code
and an empty (in terms of rows in tables) database structure. To set up
a new school i had a script that basically created a new directory in
/var/www and then within that, symlinked all of the application’s
directories from the central source folder (except the file_library
directory for obvious reasons). It would also create a copy of the
database with the same name as the root directory that it just made. The
database connection file would basically read the directory name and use
this to connect to the right database.

In this way we could clone many schools and only maintain one set of
source as long as rolled out database changes correctly (which we had a
script to do).

Now Impakt2 has become obsolite and we face re-writing the whole thing
and I’m thinking about Ruby on Rails:

My question is, is there a better way of setting up the central
structure of the application (other than the way I did it above) so that
the source is central but schools each have a seperate database (for
safety and security reasons). If you had for example 100 schools, you
wouldn’t want to be rolling out complete copies of the source to each of
the 100 seperate instances (on the same server).

I’d love to hear everyone’s suggestions as I really want to use Rails
but need to know that I won’t come unstuck right off the bat. :slight_smile:

Cheers,

Brendon M.


#2

On Thu, May 25, 2006 at 06:06:06AM +0200, Brendon M. wrote:

My question is, is there a better way of setting up the central
structure of the application (other than the way I did it above) so that
the source is central but schools each have a seperate database (for
safety and security reasons). If you had for example 100 schools, you
wouldn’t want to be rolling out complete copies of the source to each of
the 100 seperate instances (on the same server).

How about writing most of your code as a module (perhaps packaged as a
rubygem so you can do automatic upgrades), and having the MVC code
generated per installation via the script/generate command?

So, after rubygems has installed the guts of the code, you go ;

cd /var/www
rails new_site
cd new_site
script/generate myapp
vi config/database.yml

-jim


#3

I haven’t tried it, but there’s nothing stopping you from symlinking
app_name/app to a central location. Then, you could have a fresh set of
config files for stuff like the database.

However, if you’re going to do a complete rewrite, why not make the data
model support multiple schools from one instance? It’d make it a hell of
a lot easier to manage.


#4

Bryan D. wrote:

However, if you’re going to do a complete rewrite, why not make the data
model support multiple schools from one instance? It’d make it a hell of
a lot easier to manage.

That sounds interesting. I guess the problem there is that a small bug
could mean that data from one school could accidentally be displayed in
another school’s site (or something far worse). However, i’d be
interested to hear in more detail how you’d approach that :slight_smile:

Cheers :slight_smile:

Brendon


#5

Brendon M. wrote:

Bryan D. wrote:

However, if you’re going to do a complete rewrite, why not make the data
model support multiple schools from one instance? It’d make it a hell of
a lot easier to manage.

That sounds interesting. I guess the problem there is that a small bug
could mean that data from one school could accidentally be displayed in
another school’s site (or something far worse). However, i’d be
interested to hear in more detail how you’d approach that :slight_smile:

Cheers :slight_smile:

Brendon

Well, in general it means that you add another model called School, and
everything that was “top-level” before that is a child of school.

For instance, I’m assuming you have users. In your user model, you
should add a belongs_to :school. Then for stuff like pages or posts or
whatever you use to represent content, also have a belongs_to :school.

Then, the way pages get viewed would be something like:

www.yoursite.com/:school/:controller/:action/

so that you always know what stuff to do in relation to a school. As far
as making sure people from one school can’t see stuff from another, its
up to you to make sure that things that need to be protected are done so
adequately. This means that you can only add pages to a school you’re
authorized to add pages to, or whatnot.


#6

Bryan D. wrote:

www.yoursite.com/:school/:controller/:action/

so that you always know what stuff to do in relation to a school. As far
as making sure people from one school can’t see stuff from another, its
up to you to make sure that things that need to be protected are done so
adequately. This means that you can only add pages to a school you’re
authorized to add pages to, or whatnot.

In regards to that structure: Each school has their own domain name just
like any other site. Are we still then able to link www.school.co.nz to
/:school/ so that the fact that there is a :school isn’t apparent to the
end user?

I like your idea, just trying to get my head around things like
exploding the ass end out of the database with hundred’s of schools
writing rows into tables that eventually fill up (some store chat logs
and the like)? I suppose that’s a design issue. Then there’s the joy of
converting the current schema to one with a new parent. :slight_smile:

Cheers,

Brendon


#7

Jim C. wrote:

How about writing most of your code as a module (perhaps packaged as a
rubygem so you can do automatic upgrades), and having the MVC code
generated per installation via the script/generate command?

This sounds very interesting. While I’m still learning Rails (I’m
basically at the start of my journey) it sounds like a very viable way
of deploying it. Just out of interests sake (since i’m not quite up with
the play on terms in rails yet): How much more difficult or complex is
it to write the code as a module rather than a normal app? Are there any
good resources on this subject?

Cheers,

Brendon M.


#8

From what I understand, Basecamp is implemented exactly as others have
suggested, a single database with customer (in your case school)
identification based on url routing. I think that’s a pretty good
example of what can be accomplished here. Whether that’s an approach
you’re comfortable with you’ll have to determine. As far as modular
code, you might want to look into the work the Engines guys are doing.
Something like that may work for you.

Michael


#9

In regards to that structure: Each school has their own domain name just
like any other site. Are we still then able to link www.school.co.nz to
/:school/ so that the fact that there is a :school isn’t apparent to the
end user?

Well, if you end up using something like name-based virtual hosting,
even though all the domain names will point to the same server, you can
use @request.domain (or one of the other functions) to determine which
domain name the user entered. Map domain name to the school, voila, you
can take the :school out of the route.

As far as your concern about hammering a DB with tons of writes and
reads, well, how are you doing it right now? In any case, if you’re
suffering from throughput issues, you can use industry-standard load
balancing stuff like round-robin DNS or a cluster of MySQL servers to
improve access. In all, it’ll be way easier to maintain one site and
codebase instead of dozens. (I’m assuming you actually have a lot of
customers.)


#10

Bryan D. wrote:

In regards to that structure: Each school has their own domain name just
like any other site. Are we still then able to link www.school.co.nz to
/:school/ so that the fact that there is a :school isn’t apparent to the
end user?

Well, if you end up using something like name-based virtual hosting,
even though all the domain names will point to the same server, you can
use @request.domain (or one of the other functions) to determine which
domain name the user entered. Map domain name to the school, voila, you
can take the :school out of the route.

As far as your concern about hammering a DB with tons of writes and
reads, well, how are you doing it right now? In any case, if you’re
suffering from throughput issues, you can use industry-standard load
balancing stuff like round-robin DNS or a cluster of MySQL servers to
improve access. In all, it’ll be way easier to maintain one site and
codebase instead of dozens. (I’m assuming you actually have a lot of
customers.)

We’re starting to get enough customers for things to get a bit
complicated so it’s probably a good time to re-write and use the method
you suggested :slight_smile: We currently have one DB per school which allows us to
spread the load in terms of table row usage but that’s by the by.

Thanks heaps for your help, I’m going to post another message RE WYSIWYG
editors in Ruby on Rails.

Cheers,

Brendon


#11

Michael T. wrote:

From what I understand, Basecamp is implemented exactly as others have
suggested, a single database with customer (in your case school)
identification based on url routing. I think that’s a pretty good
example of what can be accomplished here. Whether that’s an approach
you’re comfortable with you’ll have to determine. As far as modular
code, you might want to look into the work the Engines guys are doing.
Something like that may work for you.

Michael

Thanks dude :slight_smile: Will look into this one :smiley: