Much exists about a situation where for example you have for example User and Admins in real life. Rather than make Admin its own class inheriting from User, you only have User and Admin is a role. (I think there are better examples.) But my question is, an Admin might have a lot of other fields, like a list of systems it can access. It seems like if you choose to use roles, you would have user objects with many empty fields that would only be non-null if the role was set to Admin. Is this okay or is there a better way to implement than using roles?
EDIT:
An idea that was suggested: Make role not an enum but a class which holds the fields unique to the role. Does this sound reasonable?
Typically, unused fields in an object point to an object decomposition problem. The usual refactoring solution is to push those fields into the objects which use them, the roles in your example, and so make them first class objects rather than just identifiers.
Related
i'm needing some help with setting up the proper relationships for my project.
The best way I can compare it is by considering a student timetable.
I need a user to be able to have many classes, and tasks within each of those classes. However, these tasks should also be linked to the user directly. I want to be able to call $user->tasks() and get all the tasks, rather than going through each $user->period.... The user has many periods, each period has many tasks, but the tasks should belong to user directly.
Any suggestions? Would i need to employ polymorphic relations in my table structure?
Thanks in advance.
It seems like what you need is the "Has Many Through" relationship.
From the docs
The "has-many-through" relationship provides a convenient short-cut
for accessing distant relations via an intermediate relation. For
example, a Country model might have many Post models through an
intermediate User model. In this example, you could easily gather all
blog posts for a given country.
In your case, it can be described as "the user has many tasks through period".
I want to run over this plan I have for achieving strong consistency with my GAE structure. Currently, here's what I have (it's really simple, I promise):
You have a Class (Class meaning Classroom not a programming "class") model and an Assignment model and also a User model. Now, a Class has an integer list property called memberIds, which is an indexed list of User ids. A class also has a string list of Assignment ids.
Anytime a new Assignment is created, its respective Class entity is also updated and adds the new Assignment id to its list.
What I want to do is get new Assignments for a user. What I do is query for all Classes where memberId = currentUserId. Each Class I get back has a list of assignment ids. I use those ids to get their respective Assignments by key. After months with this data model, I just realized that I might not get strong consistency with this (for the Class query part).
If user A posts an assignment (which consequently updates ClassA), user B who checks in for new assignments a fraction of a second later might not yet see the updated changes to ClassA (right?).
This is undesired. One solution would be to user ancestor queries, but that is not possible in my case, and entity groups are limited to 1 write per second, and I'm not sure if that's enough for my case.
So here's what I figured: anytime a new assignment is posted, we do this:
Get the respective Class entity
add the assignment id to the Class
get the ids of all this Class's members
fetch all users who are members, by keys
a User entity has a list of Classes that the user is a member of. (A LocalStructuredProperty, sort of like a dictionary:{"classId" : "242", "hasNewAssignment" : "Yes"} ). We flag that class as hasNewAssignment =
YES
Now when a user wants to get new assignments, instead of querying for groups that have a new assignment and which I am a member of, I
check the User objects list of Classes and check which classes have
new assignments.
I retrieve those classes by key (strongly consistent so far, right?)
I check the assignments list of the classes and I retrieve all assignments by key.
So throughout this process, I've never queried. All results should be strongly consistent, right? Is this a good solution? Am I overcomplicating things? Are my read/write costs skyrocketing with this? What do you think?
Queries are not strongly consistent. Gets are strongly consistent.
I think you did the right thing:
Your access is strongly consistent.
Your reads will be cheaper: one get is half cheaper as then query that returns one entity.
You writes will be more expensive: you also need to update all User entities.
So the cost depends on your usage pattern: how many assignment reads do you have vs new assignment creation.
I think using ancestor queries is a better solution.
Set the ancestor of the Assignment entities as the Class to which the assignment is allotted
Set the ancestor of a Student entity as the Class to which the student belongs.
This way all the assignments and students in a particular class belong to the same entity group. So Strong consistency is guaranteed w.r.t a query that has to deal with only a single class.
N.B. I am assuming that not too many people won't be posting assignments into a class at the same time. (but any number of people can post assignments into different classes, as they belong to different entity groups)
I have a many-to-many table that stores a record for each allowed role a user can have. If a user updates his roles (add, and removes) roles how should I handle this?
Should I delete all the users roles first and then add the selected ones? Or do some sort of matching?
There are many ways to skin this cat, a few techniques I can think of:
1. Delete all roles and re-insert
This is a straight-forward approach. Remove all the roles for the user and just re-insert. Normally the user only belong to a few roles (less than 10). Also, there is a good chance that no other foreign-keys link to this many-to-many table.
2. Keep track of the changes and apply only the changes
This is more work but more efficient, even if just slightly in this case. Tools like ORMs makes tracking and applying these type of changes a breeze.
3. Apply the changes as the user makes the change
In this case I assume that it is acceptable to apply the DB changes as the end-user associates the user to roles. Perhaps it is a local database and each transaction is short-lived. But I guess this is a unlikely scenario.
I don't think there is anything wrong for this particular case to delete and re-insert.
If a person removes a role why not pass the userID and roleID and remove that one record?
Why would you want to delete all roleID's for a specific userID and then readd them again?
From my comment above, pass two params:
UserID and RoleID
Then you can delete / extract that single tuple.
When using ldap_search to get users from Ad server, I get for each entry several objectClasses.
I'm interested only in the most specific objectClass in the classes hierarchy.
How do I get it?
for example: for the entry
name: user1
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
I want to get only the "user" objectClass.
I noticed that in the programmatic ldap_search, the most specific class is returned in the last cell of the values array, that is returned from ldap_get_values(ld, entry, "objectClass") function call. Is that by chance or is that a defined behavior?
(in other words, can I rely on this to always be true?)
Thanks for any help!
For sure you can't count on heritance order. The solution for you is to specify the objectClass attribute in your ldap search filter, and to cross with objectCategory to eliminate computers for example.
(&(objectClass=user)(objectCategory=person))
you'll receive here all the objects of class user and inetOrgPerson (they are also user).
(&(objectClass=inetOrgPerson)(objectCategory=person))
you'll receive here all the objects of class inetOrgPerson (but not those which are uniquely user).
I don't know that you can count on any inheritance order coming back from a directory. As far as I know directory results are never guaranteed to be in a specific order. Most probably return the values in the order they were specified during the add. Objectclass could be a special case and it would be specified in an RFC. Another thing you'll have to watch out for is when an object has an auxillary class that is mixed in with it. Plus that auxillary class could bring in some other parent classes. You could query the directory's schema and work out the inheritance structure from that and store that off if you're doing this all from your own program.
For a generic approach you cannot rely on objectClass values order, because it's not guaranteed by standard and because an objectclass may be derived from two or more direct superclasses (multiple inheritance).
To get the instantiated objetcclass one usually need the schema information and some extra code to analyze the object class chain.
Having said that I should also say that I've seen the code which in case of Active Directory simply relies on objectClass values order. Active Directory does not support multiple inheritance and seems always return objectClass in order or inheritance. This approach is much easier to implement, but not 100% reliable.
I am trying to wrap my head around Entity Groups in Google AppEngine. I understand them in general, but since it sounds like you can not change the relationships once the object is created AND I have a big data migration to do, I want to try to get it right the first time.
I am making an Art site where members can sign up as regular a regular Member or as one of a handful of non-polymorphic Entity "types" (Artist, Venue, Organization, ArtistRepresentative, etc). Artists, for example can have Artwork, which can in turn have other Relationships (Gallery, Media, etc). All these things are connected via References and I understand that you don't need Entity Groups to merely do References. However, some of the References NEED to exist, which is why I am looking at Entity Groups.
From the docs:
"A good rule of thumb for entity groups is that they should be about the size of a single user's worth of data or smaller."
That said, I have a couple hopefully yes/no questions.
Question 0: I gather you don't need Entity Groups just to do transactions. However, since Entity Groups are stored in the same region of Big Table, this helps cut down on consistency issues and race conditions. Is this a fair look at Entity Groups and Transactions together?
Question 1: When a child Entity is saved, do any parent objects get implicitly accessed/saved? i.e. If I set up an Entity Group with path Member/Artist/Artwork, if I save an Artwork object, do the Member and Artist objects get updated/accessed? I would think not, but I am just making sure.
Question 2: If the answer to Question 1 is yes, does the accessing/updating only travel up the path and not affect other children. i.e. If I update Artwork, no other Artwork child of Member is updated.
Question 3: Assuming it is very important that the Member and its associated account type entity exist when a user signs up and that only the user will be updating its Member and associated account type Entity, does it make sense to put these in Entity Groups together?
i.e. Member/Artist, Member/Organization, Member/Venue.
Similarly, assuming only the user will be able to update the Artwork entities, does it make sense to include those as well? Note: Media/Gallery/etc which are references to Artwork may be related to lots of Artwork, not just those owned by the user (i.e. many to many relations).
It makes sense to have all the user's bits in an entity group if it works the way I suspect (i.e. Q1/Q2 are "no"), since they will all be in the same region of BigTable. However, adding the Artwork to the entity group seems like it might violate the "keep it small" principal and honestly, may not need to be in Transactions aside from saving bandwidth/retrys when users are uploading artwork images.
Any thoughts? Am I approaching Entity Groups wrong?
0: You do need entity groups for transactions among multiple entities
1: Modifying/accessing children does not modify/access a parent
2: N/A
3: Sounds reasonable. My feeling is, entity groups should not be used unless you need transactions among them.
It is not necessary to have the the Artwork as a child for permission purposes. But if you need transactional modification to them (including e.g. creation and deletion) it might be better. For example: if you delete an account, you delete the user entity but before you delete the child, you get DeadlineExceeded or the server crashes. Now you have an orphaned Artwork. If you have more than 1,000 Artworks for an Artist, you must delete in batches.
Good luck!