A client and a contractor are both users, share some attrib but not others, how to implement as use

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

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.

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!

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 H… 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

I would suggest not creating two tables. This falls into the domain of
access control and I would recommend looking at Acl9

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.

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

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 :slight_smile:

Thanks again!
Thank you, everyone!

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

This is the plugin that I am using for roles/permissions. If you have
Rails Recipes, Chad F. is talking about something very similar.
Tim H. has done an excellent job of implementing the pattern and
it works for me.

Bharat

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!

C