I’m pretty new to database setup in Ruby and need help in setting it up correctly along with the models. Can anyone help?
Basically I have an Organisation, which will have at least 2 types of Users – Member and Admin User. Both the Organisations and the Users have an Address.
I was thinking this was basically three tables – Organisation, User and Address, but then got really confused when trying think about models and foreign keys.
Can anyone suggest the best way to organise this?
I’m running Rails 3 with a mySql database.
Thanks for your time
Sniffer
I like a lot of Adam Tanner’s answer, but I would set it up a little differently. First, the way an Organization associates with admins doesn’t work as described – you’d have to have a different foreign key in your user table, and specify that in the
has_one :adminassociation. But I don’t think that’s a good path anyway, because it limits you to one admin per organization, and limits a user belonging to one organization.My version is slightly more complicated, but I think it gets the job done well. First, admin should be a role that a user has or doesn’t have with an organization. I’ll address the user/org issue first, and save the address issue for later.
Here are the migrations, which you can enhance with whatever other fields they need:
As you can see, we’re adding a memberships table, which is going to connect users and organizations. We also add an index to speed up the association a little. Now for the models:
Here, we’re connecting our users and organizations through memberships. A user can be an admin for any of the organizations they belong to. I’ve created a few methods to set and get the admin status of a user in an organization, in the user model.
Next the addresses: I’ve already tackled this one in a blog post of mine:
http://kconrails.com/2010/10/19/common-addresses-using-polymorphism-and-nested-attributes-in-rails/
If you have any questions, please ask. Good luck!
UPDATE
Edward M. Smith pointed out in the comments that my admin methods aren’t very fault-tolerant. I was trying to keep the code as clean as possible for the example, but he has a point. So here’s the beefier version that accounts for trying to use a membership in an organization the user isn’t part of:
As always, test-driven development is best, but I usually don’t have the time to do that for stackoverflow questions 🙂