Hello All, I have a User Model at the moment that has only username, password, and roles. As you might guess, I can add to the User Model a phone column which our clients have and our contractors also have. Many other attributes may be share by both actually. But then only a client can have a "rate" column, and a company association and other things. And only a contractor can have, say, an internal FTP login/password pair. I don't quite know the nature of rules on deciding just how I should do about these un-shared attributes, I know that I use the "roles" column to differentiate a client and a contractor (learned from Raile Recipes); should I pool all attribute into User Model anyway and then find a mechanism to permit/forbid a client to see the contractor only attrib and vice versa? or two other tables one being contractor_only_properties and the other client_only_properties? I feel that having to build a table for each role seems a bit, I am very unlikely to be right, inflexible or at least un-easily-extensible (sorry for making words like this). Your (any) opinion is very valuable to me and I thank you for spending your time reading my problem All my best, Nik
on 2009-04-11 00:51
on 2009-04-11 01:00
Not knowing too much about your application, it sounds like the *only* things that a client and contractor really share is a username and password. Ignoring the "address" for a moment (as you could just create an Address model) it seems like you might have a lot of reasons for creating completely separate models: Client and Contractor. Assuming this is some sort of PM system I imagine the things they can do and the properties they have will pretty different.
on 2009-04-11 17:30
Thanks for the help Philip. -- clients and contractor get their own passwords for access to a project's home page. In the project's home page, a few things can be done by both clients and contractors and other things only one or the other party can do. And these 'things" (I am terribly sorry to have to hide them) they do are stored in several other tables. Hence my thought of using the authenticate + authorize (users/roles/rights) system from Rails Recipes. But then those sort of solid info like address, phone #1, phone #2, #3, ..., e-mail #1, #2, ..., and preferred payment column, sort of things only apply to either clients or contractor. So I was confused what to do about these columns. So you would suggest a client table and a contractor table. Thank You!
on 2009-04-11 18:54
I would suggest not creating two tables. This falls into the domain of access control and I would recommend looking at Acl9 http://github.com/be9/acl9/tree/master As for information pertaining only to clients or contractors, you could use a single User model and add contact details to it. Or you could go with straight table inheritance if phone numbers and addresses are all you need.
on 2009-04-12 11:08
I would second that. I have a project similar to yours and I have separate users and clients tables. Only keep the login information in Users table, e.g., username, encrypted_password, any other things such as layout_themes (in my case) and also a second table called clients where you keep clients specific details. here are the relationships that I have defined: class User < ActiveRecord::Base has_one :client end class Client < ActiveRecord::Base belongs_to :user end The suggestion for going with an access control system for permission and what a user and/or client can or cannot do is also an excellent one. I did extensive research and decided to go with "role_requirement" plugin by Tim Harper. It is available on Github and also comes pre-packaged with the excellent starter template "Bort" also available on Github. Needless to say, it works well with Restful_Authentication. This is a situation where you would be wise to spend some time doing up-front setup work in deciding you strategy and design. I did and it simplified my work tremendously. Hope this helps. Bharat
on 2009-04-13 15:18
Thank You Bharat And Jaryl! I am more leaning towards creating the clients and contractor's table, probably one more table called admins (another type of 'User'). But Jaryl and Bharat, I am just wondering how does a permission management sort out (or what one has to do essentially, or at least conceptually to make it sort out) that on the same table a client can enter his email, phone, address, and a few other things that a contractor also can but not SendToThisContactWhenDone column, not HowFastIWantThis column, and so on. I guess the Rails Recipe does allow me to control what action and what controller (together known as a 'right') a user with a particular 'role' can use. I think, though, my problem is slightly different from this, or is it not? It's very kind of you all, devoting your precious time on my problem. I thank you sincerely! Regards, Nik
on 2009-04-14 20:20
This is a specific case of a more general problem - how to manage inheritance in these kinds of models. There are several things to think about here. However they break down fairly easily. I'll use your specific example, but some of the observations might not make a whole lot of sense. So I will pose some questions and then give some guiding thinking. This will not be RAILS specific thinking, but bringing experience from enterprise class systems where we have things like this all the time. You can generalize the thinking questioning when the structures are even deeper. Which attributes are common between Clients/Contractors? - If there are a lot of attributes in common you might get away with a single table, and a type field in the table. Are there relationships identified that both Clients and Contractors can have? - If for example you had a security tag table and it needed to have the associated "person", and it doesn't matter if the person is a client or a contractor, then it might be worth managing that relationship via a separate table (a Person table). Do you expect to add new kinds of things? - Are Clients and Contractors the only types of Persons? Will you need to add something else in the future - e.g. Overseas Contractor which is like a Contractor but has a bunch more fields, its own processes, screens, etc. If so you may want to break into multiple tables. Do you expect to have a role concept that cuts across Clients/ Contractors? - Similar to relationships above, but let's imagine you also have roles like administrator, user, ... If those roles are independent of the Client/Contractor status, then again you might want separate tables. Do you have to worry about history/transition? - If a Client can become a Contractor (or vice versa) - and you need to manage the history (for example if all the timesheets haven't been cleared yet), then you will have to have something a bit more complex. Now you have to manage the temporal element when the Person can be both. There are lots of ways of doing that, none of them ideal! If you do decide to break into multiple tables, then make sure you manage the relationship handling among the tables inside the Model. Do not be tempted to put this into the Controller(s). Then you can treat the join of the Person with the Client or the Person with the Contractor as if they were individual Active Records. There will be performance penalties, but performance while important is not the only consideration. Hope this helps Chris
on 2009-04-15 03:01
Thank you vERY much, Chris! -- One often has moments where he/she notices something that may or may not be a real worry, but is too doubtful to speak of it. I have each of your described considerations pulsing through my head each time I think of the future of how these models will be in case of modification or deletion, but it was too vague as I had no substance to fill even a hypothetical example. But your spelling them out certainly relieved me a little. Having been thinking of these (potential) problems, it compelled me to think whether there's a kind of tutorial I can read up on some rules of thumb of deciding if table or no table and so on. I thought, a few days, ago, that in the worst case, if I made each column its own table, a Phone Model, a Gender Model, an Areacode Model, etc, basically every thing would have its own model, though unrealistically complex, it'd work ( sort of conveying that the more orthogonal bases you have, the better; in Linear Algebra). So building up a network of tables each holding exactly one column, I was thinking that, some empirical/theory-based rules for combining these hypothetical single column tables. And your Socratic method (I hope I am using this phrase right) isn't bad, at all. I will discuss with my supervisor for possible scenarios that call for minor/major table alterations, then I will begin to ask these questions myself :) Thanks again! Thank you, everyone!
on 2009-04-15 18:19
Contnuing your theme of each column being its own table - there is some sort of merit in thinking that way - at least initially. has ittle to do with rails of course, but just as a general framework of thought. If you think conceptually about things that are hard to to in relational databases and things that are easy to do. It is, for example, much harder to add a new column than a new row to an exisiting database. So, if you have a very abstracted design like this.. Entity (entity id, entity name) Rowdata (rowdataid, domainid,entityid, colname,colvalue) Domain (domainid, domain_data_type) Then you could simply add new rows into the domain table and new rows into the Rowdata table every time you want to extend the schema. This of course is far too simplistic an approach - I have mixed the schema up with the values, so it is hopelessly unnormalized), but it sort of sets the mind off onto asking the questions about when we need ultimate flexibility vs when something just needs to work simply and quickly. The answers are never as simple as you think! However, I would also say, don't dwell on the "what might possible ne..." but implement what is most reasonable. Of course it is judgement, but when developing we always have to use our judgement. When we have made a design decision about such a thorny issue, document it so you don't have to revisit the reasons. You may have to revisit the decision, so it would be handy to know why the decision was made the way it was. I do have lots of rules (of thumb and otherwise) around this stuff - but that's how I make my living! http://businessanditarchitecture.blogspot.com C
on 2009-04-16 13:52
This is the plugin that I am using for roles/permissions. If you have Rails Recipes, Chad Fowler is talking about something very similar. Tim Harper has done an excellent job of implementing the pattern and it works for me. http://github.com/timcharper/role_requirement/tree/master Bharat